diff --git a/Configurations.md b/Configurations.md index 0064f561720..e3114cf466a 100644 --- a/Configurations.md +++ b/Configurations.md @@ -389,6 +389,255 @@ fn example() { } ``` +## `chains_block_parent_indent_children` +Determines whether to indent the child chain items of a chain that begins with a block-like parent element when `indent_style` is `Block`. + +- **Default value**: `"OnlyWithParent"` +- **Possible values**: `"Always"`, `"OnlyWithParent"` +- **Stable**: No (tracking issue: ...) + +#### `OnlyWithParent` (default): +Only indent the children chain elements of a block-like parent element if the parent's body was indented. + +```rust +// chains_block_parent_indent_parent_item: "OnlyTupleLitsAndSimpleCalls" +#![rustfmt::skip] +fn example() { + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .foo() + .aaa_aaa(); + + let y = if some_condition { + // foo + val1 + } else { + // bar + val2 + } + .method_call() + .other_call() + .another(); +} +``` + +#### `Always`: +Always indent the children chain elements of a block-like parent element, regardless of whether the parent element body was indented. + +```rust +fn example() { + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .foo() + .aaa_aaa(); + + let y = if some_condition { + // foo + val1 + } else { + // bar + val2 + } + .method_call() + .other_call() + .another(); +} +``` + +See also: [`indent_style`](#indent_style), [`chains_block_parent_indent_parent_item`](#chains_block_parent_indent_parent_item). + +## `chains_block_parent_indent_parent_item` +Determines whether the body of block-like chain parents are indented when `indent_style` is `Block`. + +- **Default value**: `"Never"` +- **Possible values**: `"Always"`, `"Never"`, `"OnlySimpleCalls"`, `"OnlyTupleLitsAndSimpleCalls"` +- **Stable**: No (tracking issue: ...) + +#### `"Never"` (default): +The body of block-like parent chain elements are never indented. + +```rust +#![rustfmt::skip] +fn example() { + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} +``` + +#### `"Always"`: +The body of block-like parent chain elements are always indented. + +```rust +fn example() { + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} +``` + +#### `"OnlySimpleCalls"`: +The body of block-like parent chain elements are only indented when the parent is a simple call-like chain item, such as a method call with no multiline block like arguments (like a closure). + +```rust +fn example() { + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} +``` + +#### `"OnlyTupleLitsAndSimpleCalls"`: +The body of block-like parent chain elements are only indented when the parent is a tuple literal, or a simple call-like chain item, such as a method call with no multiline block like arguments (like a closure). + +```rust +fn example() { + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} +``` + +See also: [`indent_style`](#indent_style). + ## `comment_width` Maximum length of comments. No effect unless`wrap_comments = true`. diff --git a/src/chains.rs b/src/chains.rs index ff8d7214c54..b6f451f3277 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -61,8 +61,9 @@ use std::cmp::min; use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; +use crate::closures::rewrite_closure; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; -use crate::config::IndentStyle; +use crate::config::{ChainsBlockParentChildrenIndent, ChainsBlockParentElementIndent, IndentStyle}; use crate::expr::rewrite_call; use crate::lists::extract_pre_comment; use crate::macros::convert_try_mac; @@ -439,8 +440,7 @@ impl Rewrite for Chain { 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) + formatter.join_rewrites(context, child_shape, shape) } } @@ -471,7 +471,12 @@ trait ChainFormatter { 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, + shape: Shape, + ) -> Option; // Returns `Some` if the chain is only a root, None otherwise. fn pure_root(&mut self) -> Option; } @@ -489,6 +494,12 @@ struct ChainFormatterShared<'a> { // 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, + // Whether the parent element of the chain exceeds the max width + has_long_parent: bool, + // Whether one or more of the inner chain items exceed the max width + has_long_inner_item: bool, + // Whether the final chain item exceeds the max width + has_long_tail: bool, } impl<'a> ChainFormatterShared<'a> { @@ -498,6 +509,9 @@ impl<'a> ChainFormatterShared<'a> { rewrites: Vec::with_capacity(chain.children.len() + 1), fits_single_line: false, child_count: chain.children.len(), + has_long_parent: false, + has_long_inner_item: false, + has_long_tail: false, } } @@ -636,8 +650,14 @@ impl<'a> ChainFormatterShared<'a> { 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?); + let FormattedChainItem { + rewrite: format_last, + exceeds_max_width, + .. + } = format_chain_item(last, context, last_shape); + self.has_long_tail = exceeds_max_width; + let last_rewrite = last_subexpr_str.unwrap_or(format_last); + self.rewrites.push(last_rewrite); Some(()) } @@ -669,12 +689,17 @@ impl<'a> ChainFormatterShared<'a> { Some(result) } + + fn has_long_item(&self) -> bool { + self.has_long_parent || self.has_long_inner_item || self.has_long_tail + } } // Formats a chain using block indent. struct ChainFormatterBlock<'a> { shared: ChainFormatterShared<'a>, root_ends_with_block: bool, + parent_body_forced_indent: bool, } impl<'a> ChainFormatterBlock<'a> { @@ -682,7 +707,210 @@ impl<'a> ChainFormatterBlock<'a> { ChainFormatterBlock { shared: ChainFormatterShared::new(chain), root_ends_with_block: false, + parent_body_forced_indent: false, + } + } +} + +struct FormattedChainItem { + rewrite: String, + exceeds_max_width: bool, + forced_indent: bool, +} + +fn format_chain_item( + item: &ChainItem, + context: &RewriteContext<'_>, + shape: Shape, +) -> FormattedChainItem { + fn is_long(rewrite: String, max_width: usize, shape: Shape) -> bool { + wrap_str(rewrite, max_width, shape).is_none() + } + + fn format_chain_parent_inner( + context: &RewriteContext<'_>, + expr_kind: &ast::ExprKind, + orig_result: String, + next_line_result: String, + orig_shape: Shape, + next_shape: Shape, + ) -> FormattedChainItem { + fn contains_multiline_args( + exprs: &Vec>, + context: &RewriteContext<'_>, + shape: Shape, + ) -> bool { + exprs.iter().any(|e| match &e.kind { + ast::ExprKind::Closure( + ref capture, + ref is_async, + ref mobility, + ref fn_decl, + ref body, + ref span, + ) => match rewrite_closure( + *capture, is_async, *mobility, fn_decl, body, *span, &context, shape, + ) { + Some(rewrite) => rewrite.contains('\n'), + None => true, + }, + ast::ExprKind::Lit(ref lit) => match lit.kind { + ast::LitKind::Str(_, str_style) => match str_style { + ast::StrStyle::Raw(..) => true, + ast::StrStyle::Cooked => false, + }, + _ => false, + }, + ast::ExprKind::Struct(..) => match e.rewrite(&context, shape) { + None => true, + Some(rewrite) => !rewrite.contains('\n'), + }, + ast::ExprKind::AddrOf(_, ref expr) => match expr.kind { + ast::ExprKind::Struct(..) => match e.rewrite(&context, shape) { + None => true, + Some(rewrite) => !rewrite.contains('\n'), + }, + _ => false, + }, + _ => false, + }) + } + + fn is_simple_call_like( + parent_expr_kind: &ast::ExprKind, + context: &RewriteContext<'_>, + shape: Shape, + ) -> bool { + match parent_expr_kind { + ast::ExprKind::MethodCall(_, ref exprs) | ast::ExprKind::Call(_, ref exprs) => { + !contains_multiline_args(exprs, &context, shape) + } + _ => false, + } + } + + fn is_tup_lit_or_simple_call_like( + parent_expr_kind: &ast::ExprKind, + context: &RewriteContext<'_>, + shape: Shape, + ) -> bool { + match parent_expr_kind { + ast::ExprKind::Struct(..) => true, + _ => is_simple_call_like(parent_expr_kind, context, shape), + } + } + + let parent_indent_style = context.config.chains_block_parent_indent_parent_item(); + let should_indent = match parent_indent_style { + ChainsBlockParentElementIndent::Never => false, + ChainsBlockParentElementIndent::Always => true, + ChainsBlockParentElementIndent::OnlySimpleCalls => { + is_simple_call_like(&expr_kind, &context, orig_shape) + } + ChainsBlockParentElementIndent::OnlyTupleLitsAndSimpleCalls => { + is_tup_lit_or_simple_call_like(&expr_kind, &context, orig_shape) + } + }; + + if should_indent { + return FormattedChainItem { + rewrite: next_line_result.clone(), + exceeds_max_width: is_long( + next_line_result, + context.config.max_width(), + next_shape, + ), + forced_indent: true, + }; + } + + FormattedChainItem { + rewrite: orig_result.clone(), + exceeds_max_width: is_long(orig_result, context.config.max_width(), orig_shape), + forced_indent: false, + } + } + + let max_width = context.config.max_width(); + let orig_result = item.rewrite(context, shape); + let new_shape = match Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(shape.rhs_overhead(context.config)) + { + Some(shape) => shape, + None => { + let rewrite = context.snippet(item.span).to_owned(); + return FormattedChainItem { + rewrite: rewrite.clone(), + exceeds_max_width: is_long(rewrite, max_width, shape), + forced_indent: false, + }; + } + }; + let next_line_result = item.rewrite(context, new_shape); + match (orig_result, next_line_result) { + (Some(orig_result), _) + if !orig_result.contains('\n') + && utils::unicode_str_width(&orig_result) <= shape.width => + { + FormattedChainItem { + rewrite: orig_result.clone(), + exceeds_max_width: is_long(orig_result, max_width, shape), + forced_indent: false, + } } + (Some(orig_result), Some(next_line_result)) => match item.kind { + ChainItemKind::Parent(ref expr) => format_chain_parent_inner( + context, + &expr.kind, + orig_result, + next_line_result, + shape, + new_shape, + ), + ChainItemKind::MethodCall(_, ref types, ref exprs) + if types.is_empty() && exprs.len() == 1 => + { + if is_long(orig_result.clone(), max_width, shape) { + if is_long(next_line_result.clone(), max_width, new_shape) { + return FormattedChainItem { + rewrite: context.snippet(item.span).to_owned(), + exceeds_max_width: true, + forced_indent: false, + }; + } + return FormattedChainItem { + rewrite: next_line_result, + exceeds_max_width: false, + forced_indent: true, + }; + } + FormattedChainItem { + rewrite: orig_result, + exceeds_max_width: false, + forced_indent: false, + } + } + _ => FormattedChainItem { + rewrite: orig_result.clone(), + exceeds_max_width: is_long(orig_result, max_width, shape), + forced_indent: false, + }, + }, + (None, None) => FormattedChainItem { + rewrite: context.snippet(item.span).to_owned(), + exceeds_max_width: true, + forced_indent: false, + }, + (Some(orig_result), _) => FormattedChainItem { + rewrite: orig_result.clone(), + exceeds_max_width: is_long(orig_result, max_width, shape), + forced_indent: false, + }, + (None, Some(next_line_result)) => FormattedChainItem { + rewrite: next_line_result.clone(), + exceeds_max_width: is_long(next_line_result, max_width, new_shape), + forced_indent: true, + }, } } @@ -693,7 +921,13 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { context: &RewriteContext<'_>, shape: Shape, ) -> Option<()> { - let mut root_rewrite: String = parent.rewrite(context, shape)?; + let FormattedChainItem { + rewrite: mut root_rewrite, + exceeds_max_width, + forced_indent, + } = format_chain_item(parent, context, shape); + self.shared.has_long_inner_item = exceeds_max_width; + self.parent_body_forced_indent = forced_indent; 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); @@ -716,17 +950,27 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { break; } } + 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 { + let indent_style = context.config.chains_block_parent_indent_children(); + let use_indented = match indent_style { + ChainsBlockParentChildrenIndent::Always => true, + ChainsBlockParentChildrenIndent::OnlyWithParent if self.parent_body_forced_indent => { + true + } + _ => false, + }; Some( - if self.root_ends_with_block { - shape.block_indent(0) - } else { + if !self.root_ends_with_block || use_indented { shape.block_indent(context.config.tab_spaces()) + } else { + shape.block_indent(0) } .with_max_width(context.config), ) @@ -734,7 +978,14 @@ 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)?; + let FormattedChainItem { + rewrite, + exceeds_max_width, + .. + } = format_chain_item(&item, &context, child_shape); + if exceeds_max_width { + self.shared.has_long_inner_item = true; + } self.shared.rewrites.push(rewrite); } Some(()) @@ -750,8 +1001,17 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { .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) + fn join_rewrites( + &self, + context: &RewriteContext<'_>, + child_shape: Shape, + shape: Shape, + ) -> Option { + match self.shared.join_rewrites(context, child_shape) { + Some(rewrite) if self.shared.has_long_item() => Some(rewrite), + Some(rewrite) => wrap_str(rewrite, context.config.max_width(), shape), + None => None, + } } fn pure_root(&mut self) -> Option { @@ -764,6 +1024,7 @@ struct ChainFormatterVisual<'a> { shared: ChainFormatterShared<'a>, // The extra offset from the chain's shape to the position of the `.` offset: usize, + has_long_first_child: bool, } impl<'a> ChainFormatterVisual<'a> { @@ -771,6 +1032,7 @@ impl<'a> ChainFormatterVisual<'a> { ChainFormatterVisual { shared: ChainFormatterShared::new(chain), offset: 0, + has_long_first_child: false, } } } @@ -783,7 +1045,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { shape: Shape, ) -> Option<()> { let parent_shape = shape.visual_indent(0); - let mut root_rewrite = parent.rewrite(context, parent_shape)?; + let FormattedChainItem { + rewrite: mut root_rewrite, + exceeds_max_width: long_parent, + .. + } = format_chain_item(parent, context, parent_shape); + self.shared.has_long_parent = long_parent; let multiline = root_rewrite.contains('\n'); self.offset = if multiline { last_line_width(&root_rewrite).saturating_sub(shape.used_width()) @@ -797,18 +1064,39 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { self.shared.rewrites.push(root_rewrite); return Some(()); } - let child_shape = parent_shape - .visual_indent(self.offset) - .sub_width(self.offset)?; - let rewrite = item.rewrite(context, child_shape)?; + let child_shape = if !self.shared.has_long_parent { + parent_shape + .visual_indent(self.offset) + .sub_width(self.offset)? + } else { + let child_shape = shape.visual_indent(0); + root_rewrite.push_str(&child_shape.to_string_with_newline(context.config)); + child_shape + }; + + let FormattedChainItem { + rewrite, + exceeds_max_width: first_child_too_long, + .. + } = format_chain_item(item, context, child_shape); + self.has_long_first_child = first_child_too_long; + 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(context, parent_shape)?; + let FormattedChainItem { rewrite, .. } = + format_chain_item(item, context, parent_shape); + if self.shared.has_long_parent + || wrap_str(rewrite.clone(), context.config.max_width(), parent_shape) + .is_none() + { + self.has_long_first_child = true; + } else { + self.offset = 0; + } root_rewrite.push_str(&rewrite); - self.offset = 0; } } @@ -820,15 +1108,26 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } 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)) + if !self.shared.has_long_parent { + shape + .with_max_width(context.config) + .offset_left(self.offset) + .map(|s| s.visual_indent(0)) + } else { + Some(shape.visual_indent(0)) + } } 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)?; + let FormattedChainItem { + rewrite, + exceeds_max_width, + .. + } = format_chain_item(&item, &context, child_shape); + if exceeds_max_width { + self.shared.has_long_inner_item = true; + } self.shared.rewrites.push(rewrite); } Some(()) @@ -844,8 +1143,19 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { .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) + fn join_rewrites( + &self, + context: &RewriteContext<'_>, + child_shape: Shape, + shape: Shape, + ) -> Option { + match self.shared.join_rewrites(context, child_shape) { + Some(rewrite) if self.shared.has_long_item() || self.has_long_first_child => { + Some(rewrite) + } + Some(rewrite) => wrap_str(rewrite, context.config.max_width(), shape), + None => None, + } } fn pure_root(&mut self) -> Option { diff --git a/src/config/mod.rs b/src/config/mod.rs index 94f390ceef4..e3aeb0256d5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -65,6 +65,19 @@ create_config! { imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; merge_imports: bool, false, false, "Merge imports"; + // Chains + chains_block_parent_indent_children: + ChainsBlockParentChildrenIndent, + ChainsBlockParentChildrenIndent::OnlyWithParent, + false, + "Determines whether to indent the child chain items of a chain that beings with/ + a block-like parent element"; + chains_block_parent_indent_parent_item: + ChainsBlockParentElementIndent, + ChainsBlockParentElementIndent::Never, + false, + "Determines whether block-like chain parents are indented"; + // Ordering reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically"; reorder_modules: bool, true, true, "Reorder module statements alphabetically in group"; @@ -509,6 +522,8 @@ where_single_line = false imports_indent = "Block" imports_layout = "Mixed" merge_imports = false +chains_block_parent_indent_children = "OnlyWithParent" +chains_block_parent_indent_parent_item = "Never" reorder_imports = true reorder_modules = true reorder_impl_items = false diff --git a/src/config/options.rs b/src/config/options.rs index 4a136f4b180..adefbc80d3e 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -171,6 +171,30 @@ pub enum Verbosity { Quiet, } +#[config_type] +pub enum ChainsBlockParentElementIndent { + /// Never indent the contents of a block-like parent element. + Never, + /// Always indent the contents of a block-like parent element. + Always, + /// Only indent the contents of a block-like parent element if + /// it is a simple call-like, such as a function call that does not include + /// any block-like arguments. + OnlySimpleCalls, + /// Only indent the contents of a block-like parent element if + /// it is a tuple lit or a simple call-like, such as a function call that does not include + /// any block-like arguments. + OnlyTupleLitsAndSimpleCalls, +} + +#[config_type] +pub enum ChainsBlockParentChildrenIndent { + /// Always indent the children chain elements of a block-like parent element. + Always, + /// Only indent the children chain elements if the block-like parent body is indented. + OnlyWithParent, +} + #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct WidthHeuristics { // Maximum width of the args of a function call before falling back diff --git a/src/expr.rs b/src/expr.rs index 263c9201a46..0edece3cc32 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1957,7 +1957,12 @@ fn choose_rhs( if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) .is_none() => { - Some(format!("{}{}", before_space_str, orig_rhs)) + let prefix = if orig_rhs.starts_with('\n') || has_rhs_comment { + "" + } else { + " " + }; + Some(format!("{}{}", prefix, orig_rhs)) } (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => @@ -1971,7 +1976,14 @@ fn choose_rhs( .map(|s| format!("{}{}", before_space_str, s)) } (None, None) => None, - (Some(orig_rhs), _) => Some(format!("{}{}", before_space_str, orig_rhs)), + (Some(orig_rhs), _) => { + let prefix = if orig_rhs.starts_with('\n') || has_rhs_comment { + "" + } else { + " " + }; + Some(format!("{}{}", prefix, orig_rhs)) + } } } } diff --git a/tests/source/chains_long_items_block.rs b/tests/source/chains_long_items_block.rs new file mode 100644 index 00000000000..783c4bbe391 --- /dev/null +++ b/tests/source/chains_long_items_block.rs @@ -0,0 +1,175 @@ +// rustfmt-indent_style: Block + +// https://github.com/rust-lang/rustfmt/issues/3863 +fn issue_3863() { + foo("This text is under the max_width limit, and shouldn't cause any problems on its own.").long("But this line is extra long, and doesn't fit within 100 max_width. 1234567890123456789 aBcDeFgHiJ").baz().collect().unwrap(); +} + +// https://github.com/rust-lang/rustup.rs/pull/2097 +fn deeply_nested() { + let mut app = App::new("rustup") + .version(common::version()) + .about("The Rust toolchain installer") + .after_help(RUSTUP_HELP) + .setting(AppSettings::VersionlessSubcommands) + .setting(AppSettings::DeriveDisplayOrder) + .setting(AppSettings::SubcommandRequiredElseHelp) +.subcommand( + SubCommand::with_name("run") + .about("Run a command with an environment configured for a given toolchain") + .after_help(RUN_HELP) + .setting(AppSettings::TrailingVarArg) + .arg( + Arg::with_name("install") +.help("Install the requested toolchain if needed") +.long("install"), + ) + .arg( + Arg::with_name("toolchain") + .help(TOOLCHAIN_ARG_HELP) + .required(true), + ) + .arg( + Arg::with_name("command") + .required(true) + .multiple(true) + .use_delimiter(false), + ), + ) + .subcommand( + SubCommand::with_name("which") + .about("Display which binary will be run for a given command") + .arg(Arg::with_name("command").required(true)) + .arg( + Arg::with_name("toolchain") + .help(TOOLCHAIN_ARG_HELP) + .long("toolchain") + .takes_value(true), + ), + ) + .subcommand( + SubCommand::with_name("doc") + .alias("docs") + .about("Open the documentation for the current toolchain") + .after_help(DOC_HELP) + .arg( +Arg::with_name("path") + .long("path") + .help("Only print the path to the documentation"), + ) + .args( + &DOCS_DATA + .iter() + .map(|(name, help_msg, _)| Arg::with_name(name).long(name).help(help_msg)) + .collect::>(), + ) + .arg(Arg::with_name("toolchain") + .help(TOOLCHAIN_ARG_HELP) + .long("toolchain") + .takes_value(true), + ).group(ArgGroup::with_name("page").args( + &DOCS_DATA + .iter() + .map(|(name, _, _)| *name) + .collect::>(), + ), + ) + .arg(Arg::with_name("topic").help("Topic such as 'core', 'fn', 'usize', 'eprintln!', 'core::arch', 'alloc::format!', 'std::fs', 'std::fs::read_dir', 'std::io::Bytes', 'std::iter::Sum', 'std::io::error::Result' etc..."), + ), + ); +} + +fn inner_chain() { + let foo = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff( +Foo { + field1: val1, + field2: val2, +}.method_call().method_call(), + ).foo().bar().baz(); +} + +fn long_parent() { + // Args that do not fit + let bar = baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + // Long element no args + let foo = looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnggggggggggggggggggggggggggggggggggggggggggg().foo().bar().baz(); + + asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); + + // Long element with args that fit + let bar = looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnggggggggggggggggggggggggggggggggggggggggggg("ffffffffffffffffffffffffffffffffffff").foo().bar().baz(); + + asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("ffffffffffffffffffffffffffffffffffff").foo().bar().baz(); +} + +fn long_inner() { + // Args that do not fit + let bar = bar().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + qux().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + // Long element with args that fit + let bar = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("ffffffffffffffffffffffffffffffffffff").foo().bar().baz(); + + qux().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("ffffffffffffffffffffffffffffffffffff").foo().bar().baz(); + + // Long element no args + let foo = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); + + qux().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); +} + +fn long_tail() { + // Args that do not fit + bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).baz("fadfasdf39ru8ahsdfasdfasdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + + let foo = bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).baz("fadfasdf39ru8ahsdfasdfasdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + + // Long element with args that fit + bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff("abc123def456"); + + let foo = bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff("abc123def456"); + + // Long element no args + bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff(); + + let foo = bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff(); +} + +fn raw_str_lit() { + fpo.foo().bar.baz.quz.adfasdfasdfasdfasdfasdfasdfasffffffffffffffffffffffffffffffffffdfasf(r#" + if foo { + a(); + } + else { + b(); + } + "#.trim()); + + + fpo.foo().bar.baz.quz.a999999999999999999999999999999999999999999999999999999999999999(r#" + if foo { + a(); + } + else { + b(); + } + "#.trim().foo().bar.baz.qux().unwrap()); +} + +fn comments() { + foo.z // foo + // comment after parent + .x + .y + // comment 1 + .bar("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk") // comment after bar() +// comment 2 + .foobar +// comment after + // comment 3 + .baz(x, y, z); +} diff --git a/tests/source/chains_long_items_visual.rs b/tests/source/chains_long_items_visual.rs new file mode 100644 index 00000000000..cae919a4158 --- /dev/null +++ b/tests/source/chains_long_items_visual.rs @@ -0,0 +1,81 @@ +// rustfmt-indent_style: Visual + +fn long_parent() { + // Args that do not fit + let bar = baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + // Long element no args + let bar = bazffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf().foo().bar().baz(); + + bazffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf().foo().foo().bar().baz(); + + // Long element with args that fit + let bar = looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnggggggggggggggggggggggggggggggggggggggggggg("ffffffffffffffffffffffffffffffffffff").foo().bar().baz(); + + asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("ffffffffffffffffffffffffffffffffffff").foo().bar().baz(); +} + +fn long_first_child() { + // Args that do not fit + let bar = foo().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + foo().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + // Long element no args + let foo = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); + + qux().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); + + // Long element with args that fit + let bar = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc").foo().bar().baz(); + + qux().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc").foo().bar().baz(); +} + +fn long_inner_child() { + // Args that do not fit + let bar = foo().foo_bar.baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + foo().foo_bar.baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf").foo().bar().baz(); + + // Long element no args + let foo = bar().foo_bar.asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); + + qux().foo_bar.asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff().foo().bar().baz(); + + // Long element with args that fit + let bar = bar().foo_bar.asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc").foo().bar().baz(); + + qux().foo_bar.asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc").foo().bar().baz(); +} + +fn long_tail() { + // Args that do not fit + let bar = foo().foo_bar.foo().bar().baz().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf"); + + foo().foo_bar.foo().bar().baz().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf"); + + // Log element no args + let foo = bar().foo_bar.foo().bar().baz().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff(); + + qux().foo_bar.foo().bar().baz().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff(); + + // Long element with args that fit + bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff("abcdefghadfasdfasdfasdfasdfadf"); + + let foo = bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff("abcdefghadfasdfasdfasdfasdfadf"); +} + +fn comments() { +foo.z // foo + // comment after parent +.x.y// comment 1 + .bar("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk") // comment after bar() + // comment 2 + .foobar + // comment after + // comment 3 + .baz(x, y, z); +} diff --git a/tests/source/chains_multiline_parent_always.rs b/tests/source/chains_multiline_parent_always.rs new file mode 100644 index 00000000000..2a9a753de8e --- /dev/null +++ b/tests/source/chains_multiline_parent_always.rs @@ -0,0 +1,289 @@ +// rustfmt-chains_block_parent_indent_parent_item: Always +// rustfmt-use_small_heuristics: Off + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff(StructB { + test_test_b: other_value, + }.ddd_ddd().eee_eee()) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} + +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 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("")); +} + +impl issue_2786 { + fn thing(&self) { + foo(|a| { + println!("a"); + println!("b"); + }).bar(|c| { + println!("a"); + println!("b"); + }) + .baz(|c| { + println!("a"); + println!("b"); + }) + } +} + +fn issue_2773() { + let bar = Some(0); + bar.or_else(|| { + // do stuff + None + }).or_else(|| { + // do other stuff + None + }) + .and_then(|val| { + // do this stuff + None + }); +} + +fn issue_3034() { + disallowed_headers.iter().any(|header| *header == name) || + disallowed_header_prefixes.iter().any(|prefix| name.starts_with(prefix)) +} diff --git a/tests/source/chains_multiline_parent_never.rs b/tests/source/chains_multiline_parent_never.rs new file mode 100644 index 00000000000..ea34ca76b7f --- /dev/null +++ b/tests/source/chains_multiline_parent_never.rs @@ -0,0 +1,30 @@ +// rustfmt-chains_block_parent_indent_parent_item: Never + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + StructA { + test_test: some_value, + }.do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff(StructB { + test_test_b: other_value, + }.ddd_ddd().eee_eee()) + .bbb_bbb() + .ccc_ccc(); + let other = vec![1, 2, 3].iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + foo(|x| { + // .... + }) +.bar() +.baz() +.unwrap(); +} diff --git a/tests/source/chains_multiline_parent_simple_calls.rs b/tests/source/chains_multiline_parent_simple_calls.rs new file mode 100644 index 00000000000..7ad9063cf7a --- /dev/null +++ b/tests/source/chains_multiline_parent_simple_calls.rs @@ -0,0 +1,269 @@ +// rustfmt-chains_block_parent_indent_parent_item: OnlySimpleCalls +// rustfmt-use_small_heuristics: Off + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff(StructB { + test_test_b: other_value, + }.ddd_ddd().eee_eee()) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} + +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 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, y: val2, z: looooooooooooooooonnnnnnnnggggggg_val3 } .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 issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + 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("")); +} + +impl issue_2786 { + fn thing(&self) { + foo(|a| { + println!("a"); + println!("b"); + }).bar(|c| { + println!("a"); + println!("b"); + }) + .baz(|c| { + println!("a"); + println!("b"); + }) + } +} + +fn issue_2773() { + let bar = Some(0); + bar.or_else(|| { + // do stuff + None + }).or_else(|| { + // do other stuff + None + }) + .and_then(|val| { + // do this stuff + None + }); +} diff --git a/tests/source/chains_multiline_parent_tuples_and_simple_calls.rs b/tests/source/chains_multiline_parent_tuples_and_simple_calls.rs new file mode 100644 index 00000000000..762b94cba08 --- /dev/null +++ b/tests/source/chains_multiline_parent_tuples_and_simple_calls.rs @@ -0,0 +1,269 @@ +// rustfmt-chains_block_parent_indent_parent_item: OnlyTupleLitsAndSimpleCalls +// rustfmt-use_small_heuristics: Off + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff(StructB { + test_test_b: other_value, + }.ddd_ddd().eee_eee()) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} + +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 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, y: val2, z: looooooooooooooooonnnnnnnnggggggg_val3 } .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 issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + 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("")); +} + +impl issue_2786 { + fn thing(&self) { + foo(|a| { + println!("a"); + println!("b"); + }).bar(|c| { + println!("a"); + println!("b"); + }) + .baz(|c| { + println!("a"); + println!("b"); + }) + } +} + +fn issue_2773() { + let bar = Some(0); + bar.or_else(|| { + // do stuff + None + }).or_else(|| { + // do other stuff + None + }) + .and_then(|val| { + // do this stuff + None + }); +} diff --git a/tests/target/chains_long_items_block.rs b/tests/target/chains_long_items_block.rs new file mode 100644 index 00000000000..50b4f35ff3c --- /dev/null +++ b/tests/target/chains_long_items_block.rs @@ -0,0 +1,288 @@ +// rustfmt-indent_style: Block + +// https://github.com/rust-lang/rustfmt/issues/3863 +fn issue_3863() { + foo("This text is under the max_width limit, and shouldn't cause any problems on its own.") + .long("But this line is extra long, and doesn't fit within 100 max_width. 1234567890123456789 aBcDeFgHiJ") + .baz() + .collect() + .unwrap(); +} + +// https://github.com/rust-lang/rustup.rs/pull/2097 +fn deeply_nested() { + let mut app = App::new("rustup") + .version(common::version()) + .about("The Rust toolchain installer") + .after_help(RUSTUP_HELP) + .setting(AppSettings::VersionlessSubcommands) + .setting(AppSettings::DeriveDisplayOrder) + .setting(AppSettings::SubcommandRequiredElseHelp) + .subcommand( + SubCommand::with_name("run") + .about("Run a command with an environment configured for a given toolchain") + .after_help(RUN_HELP) + .setting(AppSettings::TrailingVarArg) + .arg( + Arg::with_name("install") + .help("Install the requested toolchain if needed") + .long("install"), + ) + .arg( + Arg::with_name("toolchain") + .help(TOOLCHAIN_ARG_HELP) + .required(true), + ) + .arg( + Arg::with_name("command") + .required(true) + .multiple(true) + .use_delimiter(false), + ), + ) + .subcommand( + SubCommand::with_name("which") + .about("Display which binary will be run for a given command") + .arg(Arg::with_name("command").required(true)) + .arg( + Arg::with_name("toolchain") + .help(TOOLCHAIN_ARG_HELP) + .long("toolchain") + .takes_value(true), + ), + ) + .subcommand( + SubCommand::with_name("doc") + .alias("docs") + .about("Open the documentation for the current toolchain") + .after_help(DOC_HELP) + .arg( + Arg::with_name("path") + .long("path") + .help("Only print the path to the documentation"), + ) + .args( + &DOCS_DATA + .iter() + .map(|(name, help_msg, _)| Arg::with_name(name).long(name).help(help_msg)) + .collect::>(), + ) + .arg( + Arg::with_name("toolchain") + .help(TOOLCHAIN_ARG_HELP) + .long("toolchain") + .takes_value(true), + ) + .group( + ArgGroup::with_name("page").args( + &DOCS_DATA + .iter() + .map(|(name, _, _)| *name) + .collect::>(), + ), + ) + .arg( + Arg::with_name("topic") + .help("Topic such as 'core', 'fn', 'usize', 'eprintln!', 'core::arch', 'alloc::format!', 'std::fs', 'std::fs::read_dir', 'std::io::Bytes', 'std::iter::Sum', 'std::io::error::Result' etc..."), + ), + ); +} + +fn inner_chain() { + let foo = bar() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff( + Foo { + field1: val1, + field2: val2, + } + .method_call() + .method_call(), + ) + .foo() + .bar() + .baz(); +} + +fn long_parent() { + // Args that do not fit + let bar = baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + // Long element no args + let foo = looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnggggggggggggggggggggggggggggggggggggggggggg() + .foo() + .bar() + .baz(); + + asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); + + // Long element with args that fit + let bar = looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnggggggggggggggggggggggggggggggggggggggggggg("ffffffffffffffffffffffffffffffffffff") + .foo() + .bar() + .baz(); + + asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("ffffffffffffffffffffffffffffffffffff") + .foo() + .bar() + .baz(); +} + +fn long_inner() { + // Args that do not fit + let bar = bar() + .baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + qux() + .baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + // Long element with args that fit + let bar = bar() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff( + "ffffffffffffffffffffffffffffffffffff", + ) + .foo() + .bar() + .baz(); + + qux() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff( + "ffffffffffffffffffffffffffffffffffff", + ) + .foo() + .bar() + .baz(); + + // Long element no args + let foo = bar() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); + + qux() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); +} + +fn long_tail() { + // Args that do not fit + bar() + .xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .baz("fadfasdf39ru8ahsdfasdfasdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + + let foo = bar() + .xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .baz("fadfasdf39ru8ahsdfasdfasdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + + // Long element with args that fit + bar() + .xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff( + "abc123def456", + ); + + let foo = bar() + .xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff( + "abc123def456", + ); + + // Long element no args + bar() + .xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff(); + + let foo = bar() + .xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff(); +} + +fn raw_str_lit() { + fpo.foo() + .bar + .baz + .quz + .adfasdfasdfasdfasdfasdfasdfasffffffffffffffffffffffffffffffffffdfasf( + r#" + if foo { + a(); + } + else { + b(); + } + "# + .trim(), + ); + + fpo.foo() + .bar + .baz + .quz + .a999999999999999999999999999999999999999999999999999999999999999( + r#" + if foo { + a(); + } + else { + b(); + } + "# + .trim() + .foo() + .bar + .baz + .qux() + .unwrap(), + ); +} + +fn comments() { + foo.z // foo + // comment after parent + .x + .y + // comment 1 + .bar("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk") // comment after bar() + // comment 2 + .foobar + // comment after + // comment 3 + .baz(x, y, z); +} diff --git a/tests/target/chains_long_items_visual.rs b/tests/target/chains_long_items_visual.rs new file mode 100644 index 00000000000..19cbff95a82 --- /dev/null +++ b/tests/target/chains_long_items_visual.rs @@ -0,0 +1,167 @@ +// rustfmt-indent_style: Visual + +fn long_parent() { + // Args that do not fit + let bar = baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + // Long element no args + let bar = bazffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf() + .foo() + .bar() + .baz(); + + bazffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf() + .foo() + .foo() + .bar() + .baz(); + + // Long element with args that fit + let bar = looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnggggggggggggggggggggggggggggggggggggggggggg("ffffffffffffffffffffffffffffffffffff") + .foo() + .bar() + .baz(); + + asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("ffffffffffffffffffffffffffffffffffff") + .foo() + .bar() + .baz(); +} + +fn long_first_child() { + // Args that do not fit + let bar = foo().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + foo().baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + // Long element no args + let foo = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); + + qux().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); + + // Long element with args that fit + let bar = bar().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc") + .foo() + .bar() + .baz(); + + qux().asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc") + .foo() + .bar() + .baz(); +} + +fn long_inner_child() { + // Args that do not fit + let bar = foo().foo_bar + .baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + foo().foo_bar + .baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf") + .foo() + .bar() + .baz(); + + // Long element no args + let foo = bar().foo_bar + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); + + qux().foo_bar + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff() + .foo() + .bar() + .baz(); + + // Long element with args that fit + let bar = bar().foo_bar + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc") + .foo() + .bar() + .baz(); + + qux().foo_bar + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff("abc") + .foo() + .bar() + .baz(); +} + +fn long_tail() { + // Args that do not fit + let bar = foo().foo_bar + .foo() + .bar() + .baz() + .baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf"); + + foo().foo_bar + .foo() + .bar() + .baz() + .baz("ffffffffffffffffffffffffffffffffffffasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfadfasdfasdfasdfadfasdfasdf"); + + // Log element no args + let foo = bar().foo_bar + .foo() + .bar() + .baz() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff(); + + qux().foo_bar + .foo() + .bar() + .baz() + .asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff(); + + // Long element with args that fit + bar().xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff("abcdefghadfasdfasdfasdfasdfadf"); + + let foo = bar().xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x) + .doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff("abcdefghadfasdfasdfasdfasdfadf"); +} + +fn comments() { + foo.z // foo + // comment after parent + .x + .y // comment 1 + .bar("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk") // comment after bar() + // comment 2 + .foobar + // comment after + // comment 3 + .baz(x, y, z); +} diff --git a/tests/target/chains_multiline_parent_always.rs b/tests/target/chains_multiline_parent_always.rs new file mode 100644 index 00000000000..33f89111243 --- /dev/null +++ b/tests/target/chains_multiline_parent_always.rs @@ -0,0 +1,333 @@ +// rustfmt-chains_block_parent_indent_parent_item: Always +// rustfmt-use_small_heuristics: Off + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} + +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 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("")); +} + +impl issue_2786 { + fn thing(&self) { + foo(|a| { + println!("a"); + println!("b"); + }) + .bar(|c| { + println!("a"); + println!("b"); + }) + .baz(|c| { + println!("a"); + println!("b"); + }) + } +} + +fn issue_2773() { + let bar = Some(0); + bar.or_else(|| { + // do stuff + None + }) + .or_else(|| { + // do other stuff + None + }) + .and_then(|val| { + // do this stuff + None + }); +} + +fn issue_3034() { + disallowed_headers.iter().any(|header| *header == name) + || disallowed_header_prefixes.iter().any(|prefix| name.starts_with(prefix)) +} diff --git a/tests/target/chains_multiline_parent_never.rs b/tests/target/chains_multiline_parent_never.rs new file mode 100644 index 00000000000..7c4095c50e9 --- /dev/null +++ b/tests/target/chains_multiline_parent_never.rs @@ -0,0 +1,36 @@ +// rustfmt-chains_block_parent_indent_parent_item: Never + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + let other = vec![1, 2, 3] + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} diff --git a/tests/target/chains_multiline_parent_simple_calls.rs b/tests/target/chains_multiline_parent_simple_calls.rs new file mode 100644 index 00000000000..2ec22e0d72f --- /dev/null +++ b/tests/target/chains_multiline_parent_simple_calls.rs @@ -0,0 +1,309 @@ +// rustfmt-chains_block_parent_indent_parent_item: OnlySimpleCalls +// rustfmt-use_small_heuristics: Off + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} + +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 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, + y: val2, + z: looooooooooooooooonnnnnnnnggggggg_val3, + } + .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 issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + 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("")); +} + +impl issue_2786 { + fn thing(&self) { + foo(|a| { + println!("a"); + println!("b"); + }) + .bar(|c| { + println!("a"); + println!("b"); + }) + .baz(|c| { + println!("a"); + println!("b"); + }) + } +} + +fn issue_2773() { + let bar = Some(0); + bar.or_else(|| { + // do stuff + None + }) + .or_else(|| { + // do other stuff + None + }) + .and_then(|val| { + // do this stuff + None + }); +} diff --git a/tests/target/chains_multiline_parent_tuples_and_simple_calls.rs b/tests/target/chains_multiline_parent_tuples_and_simple_calls.rs new file mode 100644 index 00000000000..1cf4c82f067 --- /dev/null +++ b/tests/target/chains_multiline_parent_tuples_and_simple_calls.rs @@ -0,0 +1,309 @@ +// rustfmt-chains_block_parent_indent_parent_item: OnlyTupleLitsAndSimpleCalls +// rustfmt-use_small_heuristics: Off + +fn main() { + let very_very_very_very_very_very_very_very_very_long_var_name = 13; + let all = very_very_very_very_very_long_fun_name( + very_very_very_very_very_very_very_very_very_long_var_name, + ) + .iter() + .map(|x| x + very_very_very_very_very_very_long_var_name); + + StructA { + test_test: some_value, + } + .do_stuff(StructB { + test_test_b: other_value, + }) + .aaa_aaa() + .do_stuff( + StructB { + test_test_b: other_value, + } + .ddd_ddd() + .eee_eee(), + ) + .bbb_bbb() + .ccc_ccc(); + + foo(|x| { + // .... + }) + .bar() + .baz() + .unwrap(); +} + +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 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, + y: val2, + z: looooooooooooooooonnnnnnnnggggggg_val3, + } + .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 issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + 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("")); +} + +impl issue_2786 { + fn thing(&self) { + foo(|a| { + println!("a"); + println!("b"); + }) + .bar(|c| { + println!("a"); + println!("b"); + }) + .baz(|c| { + println!("a"); + println!("b"); + }) + } +} + +fn issue_2773() { + let bar = Some(0); + bar.or_else(|| { + // do stuff + None + }) + .or_else(|| { + // do other stuff + None + }) + .and_then(|val| { + // do this stuff + None + }); +}