Skip to content

Commit d312aab

Browse files
committed
fix rust-lang#6164: Reduce format failure for non default imports_granularity
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 ...`.
1 parent 4489061 commit d312aab

9 files changed

+1014
-12
lines changed

src/imports.rs

+69-10
Original file line numberDiff line numberDiff line change
@@ -1110,8 +1110,8 @@ impl Rewrite for UseSegment {
11101110
// 1 = "{" and "}"
11111111
shape
11121112
.offset_left(1)
1113-
.and_then(|s| s.sub_width(1))
1114-
.unknown_error()?,
1113+
.unknown_error()?
1114+
.saturating_sub_width(1),
11151115
)?
11161116
}
11171117
})
@@ -1125,17 +1125,76 @@ impl Rewrite for UseTree {
11251125

11261126
// This does NOT format attributes and visibility or add a trailing `;`.
11271127
fn rewrite_result(&self, context: &RewriteContext<'_>, mut shape: Shape) -> RewriteResult {
1128+
fn proceed(
1129+
context: &RewriteContext<'_>,
1130+
shape: &Shape,
1131+
curr_segment: &UseSegment,
1132+
curr_segment_is_allow_overflow: bool,
1133+
next_segment: Option<&&UseSegment>,
1134+
) -> Option<(String, Shape)> {
1135+
let mut rewritten_segment = curr_segment.rewrite(context, shape.clone())?;
1136+
if next_segment.is_some() {
1137+
rewritten_segment.push_str("::");
1138+
}
1139+
let reserved_room_for_brace = match next_segment.map(|s| &s.kind) {
1140+
Some(UseSegmentKind::List(_)) => "{".len(),
1141+
_ => 0,
1142+
};
1143+
let next_shape = if matches!(&curr_segment.kind, UseSegmentKind::List(_)) {
1144+
// This is the last segment and we won't use `next_shape`. Return `shape`
1145+
// unchanged.
1146+
shape.clone()
1147+
} else if curr_segment_is_allow_overflow {
1148+
// If the segment follows `use ` or newline, force to consume the segment with
1149+
// overflow.
1150+
1151+
let s = shape.offset_left_maybe_overflow(rewritten_segment.len());
1152+
if s.width == 0 {
1153+
// We have to to commit current segment in this line. Make a room for next
1154+
// round.
1155+
s.add_width(reserved_room_for_brace)
1156+
} else {
1157+
s.clone()
1158+
}
1159+
} else {
1160+
let ret = shape.offset_left(rewritten_segment.len())?;
1161+
// Check that there is a room for the next "{". If not, return null for retry with
1162+
// newline.
1163+
ret.offset_left(reserved_room_for_brace)?;
1164+
ret
1165+
};
1166+
Some((rewritten_segment, next_shape))
1167+
}
1168+
1169+
let shape_top_level = shape.clone();
11281170
let mut result = String::with_capacity(256);
1171+
let mut is_first = true;
11291172
let mut iter = self.path.iter().peekable();
11301173
while let Some(segment) = iter.next() {
1131-
let segment_str = segment.rewrite_result(context, shape)?;
1132-
result.push_str(&segment_str);
1133-
if iter.peek().is_some() {
1134-
result.push_str("::");
1135-
// 2 = "::"
1136-
shape = shape
1137-
.offset_left(2 + segment_str.len())
1138-
.max_width_error(shape.width, self.span())?;
1174+
let allow_overflow = is_first;
1175+
is_first = false;
1176+
match proceed(context, &shape, segment, allow_overflow, iter.peek()) {
1177+
Some((rewritten_segment, next_shape)) => {
1178+
result.push_str(&rewritten_segment);
1179+
shape = next_shape;
1180+
continue;
1181+
}
1182+
None => (),
1183+
}
1184+
// If the first `proceed()` failed, retry with newline.
1185+
result.push_str("\n");
1186+
result.push_str(&" ".repeat(shape.indent.block_indent + 4));
1187+
shape = shape_top_level.clone();
1188+
let allow_overflow = true;
1189+
match proceed(context, &shape, segment, allow_overflow, iter.peek()) {
1190+
Some((rewritten_segment, next_shape)) => {
1191+
result.push_str(&rewritten_segment);
1192+
shape = next_shape;
1193+
}
1194+
// Give up to format.
1195+
None => {
1196+
return Err(crate::rewrite::RewriteError::Unknown);
1197+
}
11391198
}
11401199
}
11411200
Ok(result)

src/shape.rs

+11
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,13 @@ impl Shape {
242242
})
243243
}
244244

245+
pub(crate) fn add_width(&self, width: usize) -> Shape {
246+
Shape {
247+
width: self.width + width,
248+
..*self
249+
}
250+
}
251+
245252
pub(crate) fn shrink_left(&self, width: usize) -> Option<Shape> {
246253
Some(Shape {
247254
width: self.width.checked_sub(width)?,
@@ -254,6 +261,10 @@ impl Shape {
254261
self.add_offset(width).sub_width(width)
255262
}
256263

264+
pub(crate) fn offset_left_maybe_overflow(&self, width: usize) -> Shape {
265+
self.add_offset(width).saturating_sub_width(width)
266+
}
267+
257268
pub(crate) fn used_width(&self) -> usize {
258269
self.indent.block_indent + self.offset
259270
}

tests/source/5131_crate.rs

+151
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,154 @@ use foo::d::e;
1212
use qux::h;
1313
use qux::h as h2;
1414
use qux::i;
15+
16+
17+
mod indent4 {
18+
use column_____________________________________________________________________________________102::{
19+
Foo,
20+
bar::Bar,
21+
bar::baz::Baz,
22+
Foo2,
23+
bar::Bar2,
24+
};
25+
26+
use column_______________________________________________________________________________096::{
27+
Foo,
28+
bar::Bar,
29+
bar::baz::Baz,
30+
Foo2,
31+
bar::Bar2,
32+
};
33+
34+
use column_________________________________________________________________________090::{
35+
Foo,
36+
bar::Bar,
37+
bar::baz::Baz,
38+
Foo2,
39+
bar::Bar2,
40+
};
41+
42+
use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::c096::c102::{
43+
Foo,
44+
bar::Bar,
45+
bar::baz::Baz,
46+
Foo2,
47+
bar::Bar2,
48+
};
49+
50+
use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::c096::{
51+
Foo,
52+
bar::Bar,
53+
bar::baz::Baz,
54+
Foo2,
55+
bar::Bar2,
56+
};
57+
58+
use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::c090::{
59+
Foo,
60+
bar::Bar,
61+
bar::baz::Baz,
62+
Foo2,
63+
bar::Bar2,
64+
};
65+
66+
use c012::c018::c024::c030::c036::c042::c048::c054::c060::c066::c072::c078::c084::{
67+
Foo,
68+
bar::Bar,
69+
bar::baz::Baz,
70+
Foo2,
71+
bar::Bar2,
72+
};
73+
}
74+
75+
use smithay::{
76+
backend::renderer::element::{
77+
default_primary_scanout_output_compare, utils::select_dmabuf_feedback, RenderElementStates,
78+
},
79+
delegate_compositor, delegate_data_control, delegate_data_device, delegate_fractional_scale,
80+
delegate_input_method_manager, delegate_keyboard_shortcuts_inhibit, delegate_layer_shell,
81+
delegate_output, delegate_pointer_constraints, delegate_pointer_gestures,
82+
delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat,
83+
delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_text_input_manager,
84+
delegate_viewporter, delegate_virtual_keyboard_manager, delegate_xdg_activation,
85+
delegate_xdg_decoration, delegate_xdg_shell,
86+
desktop::{
87+
space::SpaceElement,
88+
utils::{
89+
surface_presentation_feedback_flags_from_states, surface_primary_scanout_output,
90+
update_surface_primary_scanout_output, OutputPresentationFeedback,
91+
},
92+
PopupKind, PopupManager, Space,
93+
},
94+
input::{
95+
keyboard::{Keysym, LedState, XkbConfig},
96+
pointer::{CursorImageStatus, PointerHandle},
97+
Seat, SeatHandler, SeatState,
98+
},
99+
output::Output,
100+
reexports::{
101+
calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
102+
wayland_protocols::xdg::decoration::{
103+
self as xdg_decoration,
104+
zv1::server::zxdg_toplevel_decoration_v1::Mode as DecorationMode,
105+
},
106+
wayland_server::{
107+
backend::{ClientData, ClientId, DisconnectReason},
108+
protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface},
109+
Display, DisplayHandle, Resource,
110+
},
111+
},
112+
utils::{Clock, Monotonic, Rectangle},
113+
wayland::{
114+
compositor::{get_parent, with_states, CompositorClientState, CompositorState},
115+
dmabuf::DmabufFeedback,
116+
fractional_scale::{
117+
with_fractional_scale, FractionalScaleHandler, FractionalScaleManagerState,
118+
},
119+
input_method::{InputMethodHandler, InputMethodManagerState, PopupSurface},
120+
keyboard_shortcuts_inhibit::{
121+
KeyboardShortcutsInhibitHandler, KeyboardShortcutsInhibitState,
122+
KeyboardShortcutsInhibitor,
123+
},
124+
output::{OutputHandler, OutputManagerState},
125+
pointer_constraints::{
126+
with_pointer_constraint, PointerConstraintsHandler, PointerConstraintsState,
127+
},
128+
pointer_gestures::PointerGesturesState,
129+
presentation::PresentationState,
130+
relative_pointer::RelativePointerManagerState,
131+
seat::WaylandFocus,
132+
security_context::{
133+
SecurityContext, SecurityContextHandler, SecurityContextListenerSource,
134+
SecurityContextState,
135+
},
136+
selection::data_device::{
137+
set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState,
138+
ServerDndGrabHandler,
139+
},
140+
selection::{
141+
primary_selection::{
142+
set_primary_focus, PrimarySelectionHandler, PrimarySelectionState,
143+
},
144+
wlr_data_control::{DataControlHandler, DataControlState},
145+
SelectionHandler,
146+
},
147+
shell::{
148+
wlr_layer::WlrLayerShellState,
149+
xdg::{
150+
decoration::{XdgDecorationHandler, XdgDecorationState},
151+
ToplevelSurface, XdgShellState, XdgToplevelSurfaceData,
152+
},
153+
},
154+
shm::{ShmHandler, ShmState},
155+
socket::ListeningSocketSource,
156+
tablet_manager::{TabletManagerState, TabletSeatTrait},
157+
text_input::TextInputManagerState,
158+
viewporter::ViewporterState,
159+
virtual_keyboard::VirtualKeyboardManagerState,
160+
xdg_activation::{
161+
XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData,
162+
},
163+
xdg_foreign::{XdgForeignHandler, XdgForeignState},
164+
},
165+
};

0 commit comments

Comments
 (0)