Skip to content

Commit b773bee

Browse files
Fix assignment LHS breaking issue
Previously, array indexing on the left-hand side of assignments could be broken across lines, resulting in undesirable formatting like: du[ i, j, 1] = alpha * expr This commit adds a custom n_ref! implementation for SciMLStyle that detects when a RefN (array reference) node is on the LHS of an assignment and prevents it from being broken across lines. The fix ensures that assignments like: du[i, j, 1] = long_expression Keep the LHS intact while still allowing the RHS to break appropriately. This addresses the issue seen in SciML/NonlinearSolve.jl#660 where array assignments were being formatted in an aesthetically unpleasing way.
1 parent 18233c6 commit b773bee

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

src/nest_utils.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ function find_optimal_nest_placeholders(
288288
return Int[]
289289
end
290290
elseif (fst.typ === Binary || fst.typ === Chain || fst.typ === Comparison)
291+
# Special handling for assignments - don't break LHS
292+
if fst.typ === Binary && !isnothing(fst.metadata) && (fst.metadata::Metadata).is_assignment
293+
# For assignments, find the operator position
294+
# Assignment structure: LHS placeholder op placeholder RHS
295+
# We want to avoid breaking before the operator
296+
if length(placeholder_inds) >= 2
297+
# Skip the first placeholder (which comes after LHS)
298+
return placeholder_inds[2:end]
299+
end
300+
end
301+
291302
# For mathematical expressions, be conservative about breaking
292303
# Only break if significantly over margin or has many operations
293304
if length(placeholder_inds) <= 3 && total_length <= max_margin + 20

src/styles/sciml/nest.jl

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,67 @@ function _n_tuple!(
220220
return nested
221221
end
222222

223+
# Custom implementation for n_ref! to prevent breaking LHS of assignments
224+
function n_ref!(
225+
ss::SciMLStyle,
226+
fst::FST,
227+
s::State,
228+
lineage::Vector{Tuple{FNode,Union{Nothing,Metadata}}},
229+
)
230+
# Check if this RefN is the LHS of an assignment
231+
# Look through the lineage to see if we have a Binary assignment parent
232+
# and this RefN comes before any other Binary operators
233+
is_lhs_of_assignment = false
234+
235+
if length(lineage) >= 2
236+
# Check if we have a Binary assignment in the lineage
237+
for i in length(lineage):-1:1
238+
if lineage[i][1] === Binary && !isnothing(lineage[i][2]) && lineage[i][2].is_assignment
239+
# Check if there are any other Binary nodes between us and the assignment
240+
has_intermediate_binary = false
241+
for j in (i+1):length(lineage)
242+
if lineage[j][1] === Binary
243+
has_intermediate_binary = true
244+
break
245+
end
246+
end
247+
248+
if !has_intermediate_binary
249+
is_lhs_of_assignment = true
250+
end
251+
break
252+
end
253+
end
254+
end
255+
256+
if is_lhs_of_assignment
257+
# Don't break the LHS of an assignment
258+
# Format children but keep them on the same line
259+
lo = s.line_offset
260+
nested = false
261+
for (i, n) in enumerate(fst.nodes)
262+
nested |= nest!(ss, n, s, lineage)
263+
if n.typ !== NEWLINE # Prevent any newlines
264+
s.line_offset += length(n)
265+
end
266+
end
267+
s.line_offset = lo + length(fst)
268+
return nested
269+
end
270+
271+
# Otherwise use the default behavior
272+
if s.opts.yas_style_nesting
273+
return n_ref!(YASStyle(getstyle(ss)), fst, s, lineage)
274+
else
275+
return _n_tuple!(getstyle(ss), fst, s, lineage)
276+
end
277+
end
278+
223279
for f in [
224280
:n_tuple!,
225281
:n_call!,
226282
:n_curly!,
227283
:n_macrocall!,
228-
:n_ref!,
229284
:n_braces!,
230285
:n_parameters!,
231286
:n_invisbrackets!,

0 commit comments

Comments
 (0)