From 25a9a5f7c3df449acda4f27450649b03fe9e0e6a Mon Sep 17 00:00:00 2001 From: Alexander Glusker Date: Fri, 29 Mar 2024 09:19:25 +0300 Subject: [PATCH] fix additional semicolon during changing parentheses style --- src/expr.rs | 3 ++- src/items.rs | 3 ++- src/macros.rs | 44 ++++++++++++++++++--------------- src/patterns.rs | 3 ++- src/types.rs | 4 ++- src/visitor.rs | 37 ++++++++++++++++----------- tests/source/issue-6013/main.rs | 7 ++++++ tests/target/issue-6013/main.rs | 9 +++++++ 8 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 tests/source/issue-6013/main.rs create mode 100644 tests/target/issue-6013/main.rs diff --git a/src/expr.rs b/src/expr.rs index 6a21d88ac9d..e84bba2b581 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -225,7 +225,8 @@ pub(crate) fn format_expr( | ast::ExprKind::MethodCall(..) | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + let (rewrite, _) = rewrite_macro(mac, None, context, shape, MacroPosition::Expression); + rewrite.or_else(|| { wrap_str( context.snippet(expr.span).to_owned(), context.config.max_width(), diff --git a/src/items.rs b/src/items.rs index e7ff5ff818b..48bdcf8d4c1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3374,7 +3374,8 @@ impl Rewrite for ast::ForeignItem { rewrite_type_alias(ty_alias, context, shape.indent, kind, span) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item) + let (rewrite, _) = rewrite_macro(mac, None, context, shape, MacroPosition::Item); + rewrite } }?; diff --git a/src/macros.rs b/src/macros.rs index 2cc5c692b22..8aa0fdeba27 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -156,13 +156,13 @@ pub(crate) fn rewrite_macro( context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, -) -> Option { +) -> (Option, Option) { let should_skip = context .skip_context .macros .skip(context.snippet(mac.path.span)); if should_skip { - None + (None, None) } else { let guard = context.enter_macro(); let result = catch_unwind(AssertUnwindSafe(|| { @@ -176,15 +176,17 @@ pub(crate) fn rewrite_macro( ) })); match result { - Err(..) | Ok(None) => { + Err(..) | Ok((None, ..)) => { context.macro_rewrite_failure.replace(true); - None + (None, None) } Ok(rw) => rw, } } } +//We return not only string but also new delimiter if it changes +//It needs to remove semicolon if delimiter changes in some situations fn rewrite_macro_inner( mac: &ast::MacCall, extra_ident: Option, @@ -192,11 +194,11 @@ fn rewrite_macro_inner( shape: Shape, position: MacroPosition, is_nested_macro: bool, -) -> Option { +) -> (Option, Option) { if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { context.leave_macro(); - return expr.rewrite(context, shape); + return (expr.rewrite(context, shape), None); } } @@ -214,7 +216,7 @@ fn rewrite_macro_inner( let ts = mac.args.tokens.clone(); let has_comment = contains_comment(context.snippet(mac.span())); if ts.is_empty() && !has_comment { - return match style { + let rewrite = match style { Delimiter::Parenthesis if position == MacroPosition::Item => { Some(format!("{macro_name}();")) } @@ -226,11 +228,12 @@ fn rewrite_macro_inner( Delimiter::Brace => Some(format!("{macro_name} {{}}")), _ => unreachable!(), }; + return (rewrite, Some(style)); } // Format well-known macros which cannot be parsed as a valid AST. if macro_name == "lazy_static!" && !has_comment { if let success @ Some(..) = format_lazy_static(context, shape, ts.clone()) { - return success; + return (success, Some(Delimiter::Brace)); } } @@ -241,17 +244,14 @@ fn rewrite_macro_inner( } = match parse_macro_args(context, ts, style, is_forced_bracket) { Some(args) => args, None => { - return return_macro_parse_failure_fallback( - context, - shape.indent, - position, - mac.span(), - ); + let rewrite = + return_macro_parse_failure_fallback(context, shape.indent, position, mac.span()); + return (rewrite, None); } }; if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) { - return rewrite_macro_with_items( + let rewrite = rewrite_macro_with_items( context, &arg_vec, ¯o_name, @@ -261,9 +261,10 @@ fn rewrite_macro_inner( position, mac.span(), ); + return (rewrite, Some(style)); } - match style { + let rewrite = match style { Delimiter::Parenthesis => { // Handle special case: `vec!(expr; expr)` if vec_with_semi { @@ -309,7 +310,7 @@ fn rewrite_macro_inner( force_trailing_comma = Some(SeparatorTactic::Vertical); }; } - let rewrite = rewrite_array( + let Some(rewrite) = rewrite_array( ¯o_name, arg_vec.iter(), mac.span(), @@ -317,12 +318,14 @@ fn rewrite_macro_inner( shape, force_trailing_comma, Some(original_style), - )?; + ) else { + return (None, None); + }; + let comma = match position { MacroPosition::Item => ";", _ => "", }; - Some(format!("{rewrite}{comma}")) } } @@ -337,7 +340,8 @@ fn rewrite_macro_inner( } } _ => unreachable!(), - } + }; + return (rewrite, Some(style)); } fn handle_vec_semi( diff --git a/src/patterns.rs b/src/patterns.rs index 0fa6edaa5d7..903a90beb2b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -269,7 +269,8 @@ impl Rewrite for Pat { shape, ), PatKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Pat) + let (rewrite, _) = rewrite_macro(mac, None, context, shape, MacroPosition::Pat); + rewrite } PatKind::Paren(ref pat) => pat .rewrite(context, shape.offset_left(1)?.sub_width(1)?) diff --git a/src/types.rs b/src/types.rs index cd2582e66be..5db8166486c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -829,7 +829,9 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Some(String::from("!")), ast::TyKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + let (rewrite, _) = + rewrite_macro(mac, None, context, shape, MacroPosition::Expression); + rewrite } ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(_, ref it) => { diff --git a/src/visitor.rs b/src/visitor.rs index 61e147ed8f5..ccc26ab5861 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -683,28 +683,38 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // 1 = ; let shape = self.shape().saturating_sub_width(1); - let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); + let original_style = macro_style(mac, &self.get_context()); + let (rewrite, rewrite_style) = + self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); // As of v638 of the rustc-ap-* crates, the associated span no longer includes // the trailing semicolon. This determines the correct span to ensure scenarios // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`) // are formatted correctly. - let (span, rewrite) = match macro_style(mac, &self.get_context()) { - Delimiter::Bracket | Delimiter::Parenthesis if MacroPosition::Item == pos => { - let search_span = mk_sp(mac.span().hi(), self.snippet_provider.end_pos()); - let hi = self.snippet_provider.span_before(search_span, ";"); - let target_span = mk_sp(mac.span().lo(), hi + BytePos(1)); - let rewrite = rewrite.map(|rw| { + let rewrite = match rewrite_style.unwrap_or(original_style) { + Delimiter::Bracket | Delimiter::Parenthesis if MacroPosition::Item == pos => rewrite + .map(|rw| { if !rw.ends_with(';') { format!("{};", rw) } else { rw } - }); - (target_span, rewrite) - } - _ => (mac.span(), rewrite), + }), + _ => rewrite, }; + let span = match original_style { + Delimiter::Bracket | Delimiter::Parenthesis + if (MacroPosition::Item == pos) + || (MacroPosition::Statement == pos) + && rewrite_style + .is_some_and(|x| x != original_style && x == Delimiter::Brace) => + { + let search_span = mk_sp(mac.span().hi(), self.snippet_provider.end_pos()); + let hi = self.snippet_provider.span_before(search_span, ";"); + mk_sp(mac.span().lo(), hi + BytePos(1)) + } + _ => mac.span(), + }; self.push_rewrite(span, rewrite); } @@ -989,13 +999,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub(crate) fn with_context(&mut self, f: F) -> Option + pub(crate) fn with_context(&mut self, f: F) -> RESULT where - F: Fn(&RewriteContext<'_>) -> Option, + F: Fn(&RewriteContext<'_>) -> RESULT, { let context = self.get_context(); let result = f(&context); - self.macro_rewrite_failure |= context.macro_rewrite_failure.get(); result } diff --git a/tests/source/issue-6013/main.rs b/tests/source/issue-6013/main.rs new file mode 100644 index 00000000000..30ce0371fc4 --- /dev/null +++ b/tests/source/issue-6013/main.rs @@ -0,0 +1,7 @@ +fn main() { +lazy_static!( + static ref DYNAMODB_CLIENT: Option = None; + static ref CASCADE_IP: String = std::env::var("CASCADE_IP").unwrap_or("127.0.0.1".to_string()); + static ref CASCADE_PORT: String = std::env::var("CASCADE_PORT").unwrap_or("4000".to_string()); +) ; +} diff --git a/tests/target/issue-6013/main.rs b/tests/target/issue-6013/main.rs new file mode 100644 index 00000000000..c6cc3a7fc89 --- /dev/null +++ b/tests/target/issue-6013/main.rs @@ -0,0 +1,9 @@ +fn main() { + lazy_static! { + static ref DYNAMODB_CLIENT: Option = None; + static ref CASCADE_IP: String = + std::env::var("CASCADE_IP").unwrap_or("127.0.0.1".to_string()); + static ref CASCADE_PORT: String = + std::env::var("CASCADE_PORT").unwrap_or("4000".to_string()); + } +}