Skip to content

Commit 0b85501

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 d5f1200 commit 0b85501

9 files changed

+995
-9
lines changed

src/imports.rs

+67-7
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ impl Rewrite for UseSegment {
10681068
context,
10691069
use_tree_list,
10701070
// 1 = "{" and "}"
1071-
shape.offset_left(1)?.sub_width(1)?,
1071+
shape.offset_left(1)?.saturating_sub_width(1),
10721072
)?,
10731073
})
10741074
}
@@ -1077,15 +1077,75 @@ impl Rewrite for UseSegment {
10771077
impl Rewrite for UseTree {
10781078
// This does NOT format attributes and visibility or add a trailing `;`.
10791079
fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
1080+
let shape_top_level = shape.clone();
10801081
let mut result = String::with_capacity(256);
1082+
let mut is_first = true;
1083+
let mut prev_is_allow_overflow = false;
10811084
let mut iter = self.path.iter().peekable();
10821085
while let Some(segment) = iter.next() {
1083-
let segment_str = segment.rewrite(context, shape)?;
1084-
result.push_str(&segment_str);
1085-
if iter.peek().is_some() {
1086-
result.push_str("::");
1087-
// 2 = "::"
1088-
shape = shape.offset_left(2 + segment_str.len())?;
1086+
// Try stacking the next segment, e.g. `use prev::next_segment::...` and
1087+
// `use prev::{next, segment}`.
1088+
let can_stack_with_constraint = (|| {
1089+
// If the segment follows `use ` or `{`, force to consume the segment with overflow.
1090+
if is_first {
1091+
let mut chunk = segment.rewrite(context, shape.infinite_width())?;
1092+
let next_shape = if iter.peek().is_some() {
1093+
chunk.push_str("::");
1094+
shape.offset_left_maybe_overflow(chunk.len())
1095+
} else {
1096+
shape.clone()
1097+
};
1098+
Some((chunk, next_shape))
1099+
} else {
1100+
// If the segment follows `use ` or newline, allow overflow by "{".
1101+
let s = if prev_is_allow_overflow
1102+
&& matches!(segment.kind, UseSegmentKind::List(_))
1103+
{
1104+
shape.add_width(1)
1105+
} else {
1106+
shape.clone()
1107+
};
1108+
let mut chunk = segment.rewrite(context, s)?;
1109+
let next_shape = match iter.peek().map(|s| &s.kind) {
1110+
Some(UseSegmentKind::List(_)) => {
1111+
chunk.push_str("::");
1112+
let ret = shape.offset_left(chunk.len())?;
1113+
// Ensure that there is a room for the next "{".
1114+
ret.offset_left(1)?;
1115+
ret
1116+
}
1117+
Some(_) => {
1118+
chunk.push_str("::");
1119+
shape.offset_left(chunk.len())?
1120+
}
1121+
None => shape.clone(),
1122+
};
1123+
Some((chunk, next_shape))
1124+
}
1125+
})();
1126+
match can_stack_with_constraint {
1127+
Some((chunk, next_shape)) => {
1128+
result.push_str(&chunk);
1129+
shape = next_shape;
1130+
prev_is_allow_overflow = is_first;
1131+
is_first = false;
1132+
}
1133+
// If the next segment exceeds the given width, continue with newline.
1134+
None => {
1135+
let segment_str = segment.rewrite(context, shape)?;
1136+
let mut chunk = format!(
1137+
"{}{}",
1138+
" ".repeat(shape.indent.block_indent + 4),
1139+
segment_str
1140+
);
1141+
if iter.peek().is_some() {
1142+
chunk.push_str("::");
1143+
}
1144+
result.push_str("\n");
1145+
result.push_str(&chunk);
1146+
shape = shape_top_level.offset_left_maybe_overflow(segment_str.len());
1147+
prev_is_allow_overflow = true;
1148+
}
10891149
}
10901150
}
10911151
Some(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)