diff --git a/src/imports.rs b/src/imports.rs index 24fee98d018..31e6c84ce42 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -1079,74 +1079,75 @@ impl Rewrite for UseSegment { impl Rewrite for UseTree { // This does NOT format attributes and visibility or add a trailing `;`. fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option { + fn proceed( + context: &RewriteContext<'_>, + shape: &Shape, + curr_segment: &UseSegment, + curr_segment_is_allow_overflow: bool, + next_segment: Option<&&UseSegment>, + ) -> Option<(String, Shape)> { + let mut rewritten_segment = curr_segment.rewrite(context, shape.clone())?; + if next_segment.is_some() { + rewritten_segment.push_str("::"); + } + let reserved_room_for_brace = match next_segment.map(|s| &s.kind) { + Some(UseSegmentKind::List(_)) => "{".len(), + _ => 0, + }; + let next_shape = if matches!(&curr_segment.kind, UseSegmentKind::List(_)) { + // This is the last segment and we won't use `next_shape`. Return `shape` + // unchanged. + shape.clone() + } else if curr_segment_is_allow_overflow { + // If the segment follows `use ` or newline, force to consume the segment with + // overflow. + + let s = shape.offset_left_maybe_overflow(rewritten_segment.len()); + if s.width == 0 { + // We have to to commit current segment in this line. Make a room for next + // round. + s.add_width(reserved_room_for_brace) + } else { + s.clone() + } + } else { + let ret = shape.offset_left(rewritten_segment.len())?; + // Check that there is a room for the next "{". If not, return null for retry with + // newline. + ret.offset_left(reserved_room_for_brace)?; + ret + }; + Some((rewritten_segment, next_shape)) + } + let shape_top_level = shape.clone(); let mut result = String::with_capacity(256); let mut is_first = true; - let mut prev_is_allow_overflow = false; let mut iter = self.path.iter().peekable(); while let Some(segment) = iter.next() { - // Try stacking the next segment, e.g. `use prev::next_segment::...` and - // `use prev::{next, segment}`. - let can_stack_with_constraint = (|| { - // If the segment follows `use ` or `{`, force to consume the segment with overflow. - if is_first { - let mut chunk = segment.rewrite(context, shape.infinite_width())?; - let next_shape = if iter.peek().is_some() { - chunk.push_str("::"); - shape.offset_left_maybe_overflow(chunk.len()) - } else { - shape.clone() - }; - Some((chunk, next_shape)) - } else { - // If the segment follows `use ` or newline, allow overflow by "{". - let s = if prev_is_allow_overflow - && matches!(segment.kind, UseSegmentKind::List(_)) - { - shape.add_width(1) - } else { - shape.clone() - }; - let mut chunk = segment.rewrite(context, s)?; - let next_shape = match iter.peek().map(|s| &s.kind) { - Some(UseSegmentKind::List(_)) => { - chunk.push_str("::"); - let ret = shape.offset_left(chunk.len())?; - // Ensure that there is a room for the next "{". - ret.offset_left(1)?; - ret - } - Some(_) => { - chunk.push_str("::"); - shape.offset_left(chunk.len())? - } - None => shape.clone(), - }; - Some((chunk, next_shape)) + let allow_overflow = is_first; + is_first = false; + match proceed(context, &shape, segment, allow_overflow, iter.peek()) { + Some((rewritten_segment, next_shape)) => { + result.push_str(&rewritten_segment); + shape = next_shape; + continue; } - })(); - match can_stack_with_constraint { - Some((chunk, next_shape)) => { - result.push_str(&chunk); + None => (), + } + // If the first `proceed()` failed, retry with newline. + result.push_str("\n"); + result.push_str(&" ".repeat(shape.indent.block_indent + 4)); + shape = shape_top_level.clone(); + let allow_overflow = true; + match proceed(context, &shape, segment, allow_overflow, iter.peek()) { + Some((rewritten_segment, next_shape)) => { + result.push_str(&rewritten_segment); shape = next_shape; - prev_is_allow_overflow = is_first; - is_first = false; } - // If the next segment exceeds the given width, continue with newline. + // Give up to format. None => { - let segment_str = segment.rewrite(context, shape)?; - let mut chunk = format!( - "{}{}", - " ".repeat(shape.indent.block_indent + 4), - segment_str - ); - if iter.peek().is_some() { - chunk.push_str("::"); - } - result.push_str("\n"); - result.push_str(&chunk); - shape = shape_top_level.offset_left_maybe_overflow(segment_str.len()); - prev_is_allow_overflow = true; + return None; } } } diff --git a/tests/source/5131_module.rs b/tests/source/5131_module.rs index bda6f458dc0..f42edb04dd2 100644 --- a/tests/source/5131_module.rs +++ b/tests/source/5131_module.rs @@ -117,6 +117,12 @@ mod indent4 { Foo2, bar::Bar2, }; + + // Test for top-level `UseSegmentKind::List`. + use { + a, + column_____________________________________________________________________________________102, + }; } use smithay::{ diff --git a/tests/target/5131_crate.rs b/tests/target/5131_crate.rs index 625865137f9..718485af17d 100644 --- a/tests/target/5131_crate.rs +++ b/tests/target/5131_crate.rs @@ -112,7 +112,9 @@ use smithay::{ set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, }, - primary_selection::{set_primary_focus, PrimarySelectionHandler, PrimarySelectionState}, + primary_selection::{ + set_primary_focus, PrimarySelectionHandler, PrimarySelectionState, + }, wlr_data_control::{DataControlHandler, DataControlState}, SelectionHandler, }, diff --git a/tests/target/5131_module.rs b/tests/target/5131_module.rs index ba480deb15f..de8568ddeae 100644 --- a/tests/target/5131_module.rs +++ b/tests/target/5131_module.rs @@ -120,6 +120,12 @@ mod indent4 { column_____________________________________________________________________________096::{ Foo, Foo2, }; + + // Test for top-level `UseSegmentKind::List`. + use { + a, + column_____________________________________________________________________________________102, + }; } use smithay::backend::renderer::element::utils::select_dmabuf_feedback; diff --git a/tests/target/5131_one.rs b/tests/target/5131_one.rs index 3fc122b300b..32c50fed0b9 100644 --- a/tests/target/5131_one.rs +++ b/tests/target/5131_one.rs @@ -115,7 +115,9 @@ use smithay::{ set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, }, - primary_selection::{set_primary_focus, PrimarySelectionHandler, PrimarySelectionState}, + primary_selection::{ + set_primary_focus, PrimarySelectionHandler, PrimarySelectionState, + }, wlr_data_control::{DataControlHandler, DataControlState}, SelectionHandler, }, diff --git a/tests/target/issue_3033.rs b/tests/target/issue_3033.rs index 92cc89201ed..7e380420ad3 100644 --- a/tests/target/issue_3033.rs +++ b/tests/target/issue_3033.rs @@ -8,5 +8,6 @@ mod indent4 { c012:: column__This_segment_wraps_because_it_exceeds_100_and_follows_the_previous_segment___102:: c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::c096:: - c012::column__This_segment_doesnt_wrap_because_it_doesnt_exceed_100__________________096::Foo; + c012::column__This_segment_doesnt_wrap_because_it_doesnt_exceed_100__________________096:: + Foo; }