2015-04-21 21:01:19 +12:00
|
|
|
// 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 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2016-05-28 00:58:25 +02:00
|
|
|
use std::borrow::Cow;
|
2015-09-07 21:34:37 +02:00
|
|
|
|
2018-04-28 15:08:58 +08:00
|
|
|
use rustc_target::spec::abi;
|
2018-04-29 20:22:48 +08:00
|
|
|
use syntax::ast::{
|
|
|
|
self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path,
|
|
|
|
Visibility, VisibilityKind,
|
|
|
|
};
|
2017-07-13 18:42:14 +09:00
|
|
|
use syntax::codemap::{BytePos, Span, NO_EXPANSION};
|
2018-04-28 15:08:58 +08:00
|
|
|
use syntax::ptr;
|
2015-06-24 01:11:29 +02:00
|
|
|
|
2017-10-07 21:58:29 +09:00
|
|
|
use rewrite::RewriteContext;
|
2017-09-17 15:23:25 +09:00
|
|
|
use shape::Shape;
|
2015-04-21 21:01:19 +12:00
|
|
|
|
2018-05-14 18:01:53 +12:00
|
|
|
pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip";
|
|
|
|
pub const SKIP_ANNOTATION: &str = "rustfmt::skip";
|
2015-06-05 16:56:59 +02:00
|
|
|
|
2018-06-25 23:36:45 +09:00
|
|
|
pub fn rewrite_ident<'a>(context: &'a RewriteContext, ident: ast::Ident) -> &'a str {
|
|
|
|
context.snippet(ident.span)
|
|
|
|
}
|
|
|
|
|
2016-03-07 13:41:32 -05:00
|
|
|
// Computes the length of a string's last line, minus offset.
|
2017-02-21 14:43:43 +13:00
|
|
|
pub fn extra_offset(text: &str, shape: Shape) -> usize {
|
2016-03-07 13:41:32 -05:00
|
|
|
match text.rfind('\n') {
|
|
|
|
// 1 for newline character
|
2018-05-14 21:58:57 +09:00
|
|
|
Some(idx) => text.len().saturating_sub(idx + 1 + shape.used_width()),
|
2016-03-07 13:41:32 -05:00
|
|
|
None => text.len(),
|
|
|
|
}
|
2015-12-27 14:25:37 +01:00
|
|
|
}
|
|
|
|
|
2018-07-20 16:18:45 +09:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 00:58:25 +02:00
|
|
|
// Uses Cow to avoid allocating in the common cases.
|
2018-06-25 23:36:45 +09:00
|
|
|
pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'static, str> {
|
2018-03-06 19:47:28 +09:00
|
|
|
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, .. } => {
|
2017-01-19 10:47:07 +13:00
|
|
|
let Path { ref segments, .. } = **path;
|
2018-06-25 23:36:45 +09:00
|
|
|
let mut segments_iter = segments.iter().map(|seg| rewrite_ident(context, seg.ident));
|
2017-01-19 10:47:07 +13:00
|
|
|
if path.is_global() {
|
2017-06-16 08:49:49 +09:00
|
|
|
segments_iter
|
|
|
|
.next()
|
|
|
|
.expect("Non-global path in pub(restricted)?");
|
2017-01-19 10:47:07 +13:00
|
|
|
}
|
2017-05-12 22:25:26 +09:00
|
|
|
let is_keyword = |s: &str| s == "self" || s == "super";
|
2017-05-17 18:57:18 +12:00
|
|
|
let path = segments_iter.collect::<Vec<_>>().join("::");
|
2017-05-12 22:25:26 +09:00
|
|
|
let in_str = if is_keyword(&path) { "" } else { "in " };
|
2016-05-28 00:58:25 +02:00
|
|
|
|
2017-05-12 22:25:26 +09:00
|
|
|
Cow::from(format!("pub({}{}) ", in_str, path))
|
2016-05-28 00:58:25 +02:00
|
|
|
}
|
2015-05-29 12:41:26 +02:00
|
|
|
}
|
|
|
|
}
|
2015-06-08 19:40:22 +02:00
|
|
|
|
2018-07-29 07:37:24 -07:00
|
|
|
#[inline]
|
2018-07-29 17:20:11 -07:00
|
|
|
pub fn format_async(is_async: ast::IsAsync) -> &'static str {
|
|
|
|
match is_async {
|
2018-07-29 07:37:24 -07:00
|
|
|
ast::IsAsync::Async { .. } => "async ",
|
|
|
|
ast::IsAsync::NotAsync => "",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-01 22:19:20 +09:00
|
|
|
#[inline]
|
|
|
|
pub fn format_constness(constness: ast::Constness) -> &'static str {
|
|
|
|
match constness {
|
|
|
|
ast::Constness::Const => "const ",
|
|
|
|
ast::Constness::NotConst => "",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 09:43:35 +09:00
|
|
|
#[inline]
|
|
|
|
pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str {
|
|
|
|
match defaultness {
|
|
|
|
ast::Defaultness::Default => "default ",
|
|
|
|
ast::Defaultness::Final => "",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-22 16:07:38 +01:00
|
|
|
#[inline]
|
|
|
|
pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str {
|
|
|
|
match unsafety {
|
|
|
|
ast::Unsafety::Unsafe => "unsafe ",
|
|
|
|
ast::Unsafety::Normal => "",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-20 17:31:31 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn format_auto(is_auto: ast::IsAuto) -> &'static str {
|
|
|
|
match is_auto {
|
|
|
|
ast::IsAuto::Yes => "auto ",
|
|
|
|
ast::IsAuto::No => "",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-24 19:54:38 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn format_mutability(mutability: ast::Mutability) -> &'static str {
|
|
|
|
match mutability {
|
2016-03-01 17:27:19 -05:00
|
|
|
ast::Mutability::Mutable => "mut ",
|
|
|
|
ast::Mutability::Immutable => "",
|
2015-07-24 19:54:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-22 16:07:38 +01:00
|
|
|
#[inline]
|
2017-09-29 15:08:48 +09:00
|
|
|
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 {
|
2017-09-15 18:11:24 +09:00
|
|
|
Cow::from("extern ")
|
2016-04-18 18:39:40 +02:00
|
|
|
} else {
|
2017-09-15 18:11:24 +09:00
|
|
|
Cow::from(format!("extern {} ", abi))
|
2016-04-18 18:39:40 +02:00
|
|
|
}
|
2015-11-22 16:07:38 +01:00
|
|
|
}
|
|
|
|
|
2017-09-15 22:27:20 +09:00
|
|
|
#[inline]
|
|
|
|
// Transform `Vec<syntax::ptr::P<T>>` into `Vec<&T>`
|
|
|
|
pub fn ptr_vec_to_ref_vec<T>(vec: &[ptr::P<T>]) -> Vec<&T> {
|
|
|
|
vec.iter().map(|x| &**x).collect::<Vec<_>>()
|
|
|
|
}
|
|
|
|
|
2017-08-05 15:21:46 +09:00
|
|
|
#[inline]
|
|
|
|
pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec<ast::Attribute> {
|
|
|
|
attrs
|
|
|
|
.iter()
|
|
|
|
.filter(|a| a.style == style)
|
|
|
|
.cloned()
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec<ast::Attribute> {
|
|
|
|
filter_attributes(attrs, ast::AttrStyle::Inner)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec<ast::Attribute> {
|
|
|
|
filter_attributes(attrs, ast::AttrStyle::Outer)
|
|
|
|
}
|
|
|
|
|
2018-04-28 13:59:03 +09:00
|
|
|
#[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("//"))
|
|
|
|
}
|
|
|
|
|
2017-08-11 17:52:13 +09:00
|
|
|
#[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 {
|
2017-08-29 22:16:04 +09:00
|
|
|
!attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str)
|
2017-08-11 17:52:13 +09:00
|
|
|
}
|
|
|
|
|
2015-08-14 20:00:22 +12:00
|
|
|
// 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') {
|
2015-08-17 09:41:45 +12:00
|
|
|
Some(n) => s.len() - n - 1,
|
2015-08-14 20:00:22 +12:00
|
|
|
None => s.len(),
|
|
|
|
}
|
|
|
|
}
|
2017-06-15 16:26:41 +09:00
|
|
|
|
2017-08-01 22:19:20 +09:00
|
|
|
// 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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-12 10:30:57 +12:00
|
|
|
#[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(),
|
|
|
|
}
|
|
|
|
}
|
2015-08-14 20:00:22 +12:00
|
|
|
|
2017-06-17 21:11:55 +09:00
|
|
|
#[inline]
|
|
|
|
pub fn last_line_extendable(s: &str) -> bool {
|
2017-10-07 22:17:01 +09:00
|
|
|
if s.ends_with("\"#") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for c in s.chars().rev() {
|
|
|
|
match c {
|
2018-02-06 09:36:29 +09:00
|
|
|
'(' | ')' | ']' | '}' | '?' | '>' => continue,
|
2017-10-07 22:17:01 +09:00
|
|
|
'\n' => break,
|
|
|
|
_ if c.is_whitespace() => continue,
|
|
|
|
_ => return false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
2017-06-17 21:11:55 +09:00
|
|
|
}
|
|
|
|
|
2015-08-14 20:00:22 +12:00
|
|
|
#[inline]
|
2015-06-23 15:58:58 +02:00
|
|
|
fn is_skip(meta_item: &MetaItem) -> bool {
|
|
|
|
match meta_item.node {
|
2018-05-14 16:11:55 +12:00
|
|
|
MetaItemKind::Word => {
|
|
|
|
let path_str = meta_item.ident.to_string();
|
|
|
|
path_str == SKIP_ANNOTATION || path_str == DEPR_SKIP_ANNOTATION
|
|
|
|
}
|
2016-12-23 11:13:00 -08:00
|
|
|
MetaItemKind::List(ref l) => {
|
2018-05-06 09:57:26 +12:00
|
|
|
meta_item.name() == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1])
|
2016-09-16 15:19:18 +12:00
|
|
|
}
|
2015-06-23 15:58:58 +02:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-16 15:19:18 +12:00
|
|
|
#[inline]
|
|
|
|
fn is_skip_nested(meta_item: &NestedMetaItem) -> bool {
|
|
|
|
match meta_item.node {
|
|
|
|
NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi),
|
|
|
|
NestedMetaItemKind::Literal(_) => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-23 15:58:58 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn contains_skip(attrs: &[Attribute]) -> bool {
|
2017-06-16 08:49:49 +09:00
|
|
|
attrs
|
|
|
|
.iter()
|
|
|
|
.any(|a| a.meta().map_or(false, |a| is_skip(&a)))
|
2015-06-23 15:58:58 +02:00
|
|
|
}
|
|
|
|
|
2015-11-17 22:53:06 -06:00
|
|
|
#[inline]
|
2017-07-11 22:41:38 +09:00
|
|
|
pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool {
|
2015-11-17 22:53:06 -06:00
|
|
|
match expr.node {
|
2017-07-11 22:41:38 +09:00
|
|
|
ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => {
|
|
|
|
context.config.trailing_semicolon()
|
|
|
|
}
|
2015-11-17 22:53:06 -06:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2017-07-11 22:41:38 +09:00
|
|
|
pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool {
|
2015-11-17 22:53:06 -06:00
|
|
|
match stmt.node {
|
2017-07-11 21:53:10 +09:00
|
|
|
ast::StmtKind::Semi(ref expr) => match expr.node {
|
2017-11-16 16:42:07 +09:00
|
|
|
ast::ExprKind::While(..)
|
|
|
|
| ast::ExprKind::WhileLet(..)
|
|
|
|
| ast::ExprKind::Loop(..)
|
|
|
|
| ast::ExprKind::ForLoop(..) => false,
|
2017-07-11 22:41:38 +09:00
|
|
|
ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => {
|
|
|
|
context.config.trailing_semicolon()
|
|
|
|
}
|
2017-07-11 21:53:10 +09:00
|
|
|
_ => true,
|
|
|
|
},
|
2016-03-01 17:27:19 -05:00
|
|
|
ast::StmtKind::Expr(..) => false,
|
2015-11-17 22:53:06 -06:00
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-16 15:19:18 +12:00
|
|
|
#[inline]
|
|
|
|
pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> {
|
|
|
|
match stmt.node {
|
|
|
|
ast::StmtKind::Expr(ref expr) => Some(expr),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-05 15:17:40 +09:00
|
|
|
#[inline]
|
|
|
|
pub fn count_newlines(input: &str) -> usize {
|
2018-03-21 23:58:23 +09:00
|
|
|
// Using `as_bytes` to omit UTF-8 decoding
|
|
|
|
input.as_bytes().iter().filter(|&&c| c == b'\n').count()
|
2017-12-05 15:17:40 +09:00
|
|
|
}
|
|
|
|
|
2016-07-26 06:20:01 +01:00
|
|
|
// 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 {
|
2018-03-22 16:09:21 +09:00
|
|
|
($this:ident, $sp:expr) => {
|
2017-06-06 06:54:22 +02:00
|
|
|
$sp.source_callsite()
|
2018-02-04 12:09:03 +00:00
|
|
|
};
|
2017-06-06 06:54:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
|
2017-08-19 21:47:40 +03:00
|
|
|
Span::new(lo, hi, NO_EXPANSION)
|
2016-07-26 06:20:01 +01:00
|
|
|
}
|
2016-04-06 10:04:29 +05:30
|
|
|
|
2017-07-29 12:51:45 +09:00
|
|
|
// Return true if the given span does not intersect with file lines.
|
|
|
|
macro_rules! out_of_file_lines_range {
|
2018-03-22 16:09:21 +09:00
|
|
|
($self:ident, $span:expr) => {
|
2018-07-06 11:58:22 +12:00
|
|
|
!$self.config.file_lines().is_all() && !$self
|
|
|
|
.config
|
|
|
|
.file_lines()
|
|
|
|
.intersects(&$self.codemap.lookup_line_range($span))
|
2018-02-04 12:09:03 +00:00
|
|
|
};
|
2017-07-29 12:51:45 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! skip_out_of_file_lines_range {
|
2018-03-22 16:09:21 +09:00
|
|
|
($self:ident, $span:expr) => {
|
2017-07-29 12:51:45 +09:00
|
|
|
if out_of_file_lines_range!($self, $span) {
|
|
|
|
return None;
|
|
|
|
}
|
2018-02-04 12:09:03 +00:00
|
|
|
};
|
2017-07-29 12:51:45 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! skip_out_of_file_lines_range_visitor {
|
2018-03-22 16:09:21 +09:00
|
|
|
($self:ident, $span:expr) => {
|
2017-07-29 12:51:45 +09:00
|
|
|
if out_of_file_lines_range!($self, $span) {
|
2017-07-29 17:06:50 +02:00
|
|
|
$self.push_rewrite($span, None);
|
2017-07-29 12:51:45 +09:00
|
|
|
return;
|
|
|
|
}
|
2018-02-04 12:09:03 +00:00
|
|
|
};
|
2017-07-29 12:51:45 +09:00
|
|
|
}
|
|
|
|
|
2017-10-07 22:14:33 +09:00
|
|
|
// Wraps String in an Option. Returns Some when the string adheres to the
|
2018-07-07 12:24:09 +02:00
|
|
|
// Rewrite constraints defined for the Rewrite trait and None otherwise.
|
2017-10-07 22:04:02 +09:00
|
|
|
pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option<String> {
|
2017-10-07 22:14:33 +09:00
|
|
|
if is_valid_str(&s, max_width, shape) {
|
|
|
|
Some(s)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2015-09-04 18:09:05 +02:00
|
|
|
|
2017-10-07 22:14:33 +09:00
|
|
|
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;
|
2015-09-04 18:09:05 +02:00
|
|
|
}
|
|
|
|
}
|
2017-10-07 22:14:33 +09:00
|
|
|
true
|
2015-09-04 18:09:05 +02:00
|
|
|
}
|
|
|
|
|
2017-03-28 23:14:48 +09:00
|
|
|
#[inline]
|
2017-03-28 23:16:52 +09:00
|
|
|
pub fn colon_spaces(before: bool, after: bool) -> &'static str {
|
2017-03-28 23:14:48 +09:00
|
|
|
match (before, after) {
|
|
|
|
(true, true) => " : ",
|
|
|
|
(true, false) => " :",
|
|
|
|
(false, true) => ": ",
|
|
|
|
(false, false) => ":",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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))
}
}
```
2018-07-11 21:01:40 +12:00
|
|
|
#[inline]
|
2016-04-14 08:36:59 +12:00
|
|
|
pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr {
|
|
|
|
match e.node {
|
2018-04-06 23:09:45 +09:00
|
|
|
ast::ExprKind::Call(ref e, _)
|
2017-11-16 16:42:07 +09:00
|
|
|
| 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::Index(ref e, _)
|
|
|
|
| ast::ExprKind::Range(Some(ref e), _, _)
|
|
|
|
| ast::ExprKind::Try(ref e) => left_most_sub_expr(e),
|
2016-04-14 08:36:59 +12:00
|
|
|
_ => e,
|
|
|
|
}
|
|
|
|
}
|
2017-08-15 16:49:02 +09:00
|
|
|
|
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))
}
}
```
2018-07-11 21:01:40 +12:00
|
|
|
#[inline]
|
2017-10-05 00:23:17 +09:00
|
|
|
pub fn starts_with_newline(s: &str) -> bool {
|
|
|
|
s.starts_with('\n') || s.starts_with("\r\n")
|
|
|
|
}
|
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))
}
}
```
2018-07-11 21:01:40 +12:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn first_line_ends_with(s: &str, c: char) -> bool {
|
|
|
|
s.lines().next().map_or(false, |l| l.ends_with(c))
|
|
|
|
}
|