Skip to content

Commit

Permalink
fix #6164: Reduce format failure for non default imports_granularity
Browse files Browse the repository at this point in the history
This patch reduces format failure for non default `imports_granularity`
and correct the behavior around some edge cases.

- Supports too long line of `use ...` that contains `{}`.
- Fixes the width calculation of too long lines of `use ...`.
  • Loading branch information
kenoss committed Jun 25, 2024
1 parent e494418 commit 041d1c0
Show file tree
Hide file tree
Showing 9 changed files with 995 additions and 9 deletions.
74 changes: 67 additions & 7 deletions src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ impl Rewrite for UseSegment {
context,
use_tree_list,
// 1 = "{" and "}"
shape.offset_left(1)?.sub_width(1)?,
shape.offset_left(1)?.saturating_sub_width(1),
)?,
})
}
Expand All @@ -1079,15 +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<String> {
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() {
let segment_str = segment.rewrite(context, shape)?;
result.push_str(&segment_str);
if iter.peek().is_some() {
result.push_str("::");
// 2 = "::"
shape = shape.offset_left(2 + segment_str.len())?;
// 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))
}
})();
match can_stack_with_constraint {
Some((chunk, next_shape)) => {
result.push_str(&chunk);
shape = next_shape;
prev_is_allow_overflow = is_first;
is_first = false;
}
// If the next segment exceeds the given width, continue with newline.
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;
}
}
}
Some(result)
Expand Down
11 changes: 11 additions & 0 deletions src/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,13 @@ impl Shape {
})
}

pub(crate) fn add_width(&self, width: usize) -> Shape {
Shape {
width: self.width + width,
..*self
}
}

pub(crate) fn shrink_left(&self, width: usize) -> Option<Shape> {
Some(Shape {
width: self.width.checked_sub(width)?,
Expand All @@ -254,6 +261,10 @@ impl Shape {
self.add_offset(width).sub_width(width)
}

pub(crate) fn offset_left_maybe_overflow(&self, width: usize) -> Shape {
self.add_offset(width).saturating_sub_width(width)
}

pub(crate) fn used_width(&self) -> usize {
self.indent.block_indent + self.offset
}
Expand Down
151 changes: 151 additions & 0 deletions tests/source/5131_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,154 @@ use foo::d::e;
use qux::h;
use qux::h as h2;
use qux::i;


mod indent4 {
use column_____________________________________________________________________________________102::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};

use column_______________________________________________________________________________096::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};

use column_________________________________________________________________________090::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};

use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::c096::c102::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};

use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::c096::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};

use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};

use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::{
Foo,
bar::Bar,
bar::baz::Baz,
Foo2,
bar::Bar2,
};
}

use smithay::{
backend::renderer::element::{
default_primary_scanout_output_compare, utils::select_dmabuf_feedback, RenderElementStates,
},
delegate_compositor, delegate_data_control, delegate_data_device, delegate_fractional_scale,
delegate_input_method_manager, delegate_keyboard_shortcuts_inhibit, delegate_layer_shell,
delegate_output, delegate_pointer_constraints, delegate_pointer_gestures,
delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat,
delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_text_input_manager,
delegate_viewporter, delegate_virtual_keyboard_manager, delegate_xdg_activation,
delegate_xdg_decoration, delegate_xdg_shell,
desktop::{
space::SpaceElement,
utils::{
surface_presentation_feedback_flags_from_states, surface_primary_scanout_output,
update_surface_primary_scanout_output, OutputPresentationFeedback,
},
PopupKind, PopupManager, Space,
},
input::{
keyboard::{Keysym, LedState, XkbConfig},
pointer::{CursorImageStatus, PointerHandle},
Seat, SeatHandler, SeatState,
},
output::Output,
reexports::{
calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
wayland_protocols::xdg::decoration::{
self as xdg_decoration,
zv1::server::zxdg_toplevel_decoration_v1::Mode as DecorationMode,
},
wayland_server::{
backend::{ClientData, ClientId, DisconnectReason},
protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface},
Display, DisplayHandle, Resource,
},
},
utils::{Clock, Monotonic, Rectangle},
wayland::{
compositor::{get_parent, with_states, CompositorClientState, CompositorState},
dmabuf::DmabufFeedback,
fractional_scale::{
with_fractional_scale, FractionalScaleHandler, FractionalScaleManagerState,
},
input_method::{InputMethodHandler, InputMethodManagerState, PopupSurface},
keyboard_shortcuts_inhibit::{
KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState,
KeyboardShortcutsInhibitor,
},
output::{OutputHandler, OutputManagerState},
pointer_constraints::{
with_pointer_constraint, PointerConstraintsHandler, PointerConstraintsState,
},
pointer_gestures::PointerGesturesState,
presentation::PresentationState,
relative_pointer::RelativePointerManagerState,
seat::WaylandFocus,
security_context::{
SecurityContext, SecurityContextHandler, SecurityContextListenerSource,
SecurityContextState,
},
selection::data_device::{
set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState,
ServerDndGrabHandler,
},
selection::{
primary_selection::{
set_primary_focus, PrimarySelectionHandler, PrimarySelectionState,
},
wlr_data_control::{DataControlHandler, DataControlState},
SelectionHandler,
},
shell::{
wlr_layer::WlrLayerShellState,
xdg::{
decoration::{XdgDecorationHandler, XdgDecorationState},
ToplevelSurface, XdgShellState, XdgToplevelSurfaceData,
},
},
shm::{ShmHandler, ShmState},
socket::ListeningSocketSource,
tablet_manager::{TabletManagerState, TabletSeatTrait},
text_input::TextInputManagerState,
viewporter::ViewporterState,
virtual_keyboard::VirtualKeyboardManagerState,
xdg_activation::{
XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData,
},
xdg_foreign::{XdgForeignHandler, XdgForeignState},
},
};
Loading

0 comments on commit 041d1c0

Please sign in to comment.