fix more indents#1231
Conversation
|
This was Opus 5. So, honestly, glancing through this I think that the fix is sound i.e. it's fundamentally the right fix and isn't just papering over the cracks. I will review it carefully but I'm pretty impressed by it because I've seen LLMs generate terrible fixes for JuliaFormatter plenty of times now |
| one of them that has already been split over several lines. | ||
| """ | ||
| function is_column_aligned(fst::FST) | ||
| if is_leaf(fst) |
There was a problem hiding this comment.
return if ...
How about binaries?
There was a problem hiding this comment.
Yes confirmed there are still bugs with binaries
There was a problem hiding this comment.
Some bugs with binaries have been squashed but some issues with pathological inputs still remain (see #1232)
|
!formatbot penelopeysm/FlexiChains.jl --ignore-config --style=yas |
|
!formatbot JuliaLang/julia@v1.12.6 --ignore-config --style=yas |
FormatBot Results
Diff (872 bytes)diff --git a/ext/FlexiChainsDynamicPPLExt.jl b/ext/FlexiChainsDynamicPPLExt.jl
index bc0394b..589ebe0 100644
--- a/ext/FlexiChainsDynamicPPLExt.jl
+++ b/ext/FlexiChainsDynamicPPLExt.jl
@@ -485,7 +485,7 @@ function DynamicPPL.predict(rng::Random.AbstractRNG,
for
(vn, val) in pairs(vnt)
if (include_all || !(vn in
- existing_parameters)))
+ existing_parameters)))
# Use skeletons from reevaluation, since they will be appropriate for the new
# chain that we are constructing.
skeleton = DynamicPPL.skeleton(vnt)
|
|
Yes, that's exactly the inverse of the previous PR! |
FormatBot Results
Caution Formatting with base and PR is not idempotent! Diff (19850 bytes)diff --git a/Compiler/src/tfuncs.jl b/Compiler/src/tfuncs.jl
index 166f1fd..7cf917e 100644
--- a/Compiler/src/tfuncs.jl
+++ b/Compiler/src/tfuncs.jl
@@ -3062,11 +3062,11 @@ function is_pure_intrinsic_infer(f::IntrinsicFunction,
is_effect_free = _is_effect_free_infer(f)
end
return is_effect_free && !(f === Intrinsics.llvmcall || # can do arbitrary things
- f === Intrinsics.atomic_pointermodify || # can do arbitrary things
- f === Intrinsics.pointerref || # this one is volatile
- f === Intrinsics.sqrt_llvm_fast || # this one may differ at runtime (by a few ulps)
- f === Intrinsics.have_fma || # this one depends on the runtime environment
- f === Intrinsics.cglobal) # cglobal lookup answer changes at runtime
+ f === Intrinsics.atomic_pointermodify || # can do arbitrary things
+ f === Intrinsics.pointerref || # this one is volatile
+ f === Intrinsics.sqrt_llvm_fast || # this one may differ at runtime (by a few ulps)
+ f === Intrinsics.have_fma || # this one depends on the runtime environment
+ f === Intrinsics.cglobal) # cglobal lookup answer changes at runtime
end
function intrinsic_effects(f::IntrinsicFunction, argtypes::Vector{Any})
diff --git a/Compiler/src/validation.jl b/Compiler/src/validation.jl
index 4c16cad..877b37e 100644
--- a/Compiler/src/validation.jl
+++ b/Compiler/src/validation.jl
@@ -275,8 +275,8 @@ end
function is_valid_rvalue(@nospecialize(x))
is_valid_argument(x) && return true
if isa(x, Expr) && x.head in (:new, :splatnew, :the_exception, :isdefined, :call,
- :invoke, :invoke_modify, :foreigncall, :cfunction, :gc_preserve_begin, :copyast,
- :new_opaque_closure)
+ :invoke, :invoke_modify, :foreigncall, :cfunction, :gc_preserve_begin, :copyast,
+ :new_opaque_closure)
return true
end
return false
diff --git a/base/lock.jl b/base/lock.jl
index 4dcd131..b9a9187 100644
--- a/base/lock.jl
+++ b/base/lock.jl
@@ -194,57 +194,57 @@ Each `lock` must be matched by an [`unlock`](@ref).
"""
@inline function lock(rl::ReentrantLock)
trylock(rl) || (@noinline function slowlock(rl::ReentrantLock)
- Threads.lock_profiling() && Threads.inc_lock_conflict_count()
- c = rl.cond_wait
- ct = current_task()
- iteration = 1
- while true
- state = @atomic :monotonic rl.havelock
- # Grab the lock if it isn't locked, even if there is a queue on it
- if state & LOCKED_BIT == 0
- GC.disable_finalizers()
- result = (@atomicreplace :acquire :monotonic rl.havelock state =>
- (state | LOCKED_BIT))
- if result.success
- rl.reentrancy_cnt = 0x0000_0001
- @atomic :release rl.locked_by = ct
- return
- end
- GC.enable_finalizers()
- continue
- end
+ Threads.lock_profiling() && Threads.inc_lock_conflict_count()
+ c = rl.cond_wait
+ ct = current_task()
+ iteration = 1
+ while true
+ state = @atomic :monotonic rl.havelock
+ # Grab the lock if it isn't locked, even if there is a queue on it
+ if state & LOCKED_BIT == 0
+ GC.disable_finalizers()
+ result = (@atomicreplace :acquire :monotonic rl.havelock state =>
+ (state | LOCKED_BIT))
+ if result.success
+ rl.reentrancy_cnt = 0x0000_0001
+ @atomic :release rl.locked_by = ct
+ return
+ end
+ GC.enable_finalizers()
+ continue
+ end
- if state & PARKED_BIT == 0
- # If there is no queue, try spinning a few times
- if iteration <= MAX_SPIN_ITERS
- Base.yield()
- iteration += 1
- continue
- end
+ if state & PARKED_BIT == 0
+ # If there is no queue, try spinning a few times
+ if iteration <= MAX_SPIN_ITERS
+ Base.yield()
+ iteration += 1
+ continue
+ end
- # If still not locked, try setting the parked bit
- @atomicreplace :monotonic :monotonic rl.havelock state =>
- (state | PARKED_BIT)
- end
+ # If still not locked, try setting the parked bit
+ @atomicreplace :monotonic :monotonic rl.havelock state =>
+ (state | PARKED_BIT)
+ end
- # lock the `cond_wait`
- lock(c.lock)
+ # lock the `cond_wait`
+ lock(c.lock)
- # Last check before we wait to make sure `unlock` did not win the race
- # to the `cond_wait` lock and cleared the parked bit
- state = @atomic :acquire rl.havelock
- if state != LOCKED_BIT | PARKED_BIT
- unlock(c.lock)
- continue
- end
+ # Last check before we wait to make sure `unlock` did not win the race
+ # to the `cond_wait` lock and cleared the parked bit
+ state = @atomic :acquire rl.havelock
+ if state != LOCKED_BIT | PARKED_BIT
+ unlock(c.lock)
+ continue
+ end
- # It was locked, so now wait for the unlock to notify us
- wait_no_relock(c)
+ # It was locked, so now wait for the unlock to notify us
+ wait_no_relock(c)
- # Loop back and try locking again
- iteration = 1
- end
- end)(rl)
+ # Loop back and try locking again
+ iteration = 1
+ end
+ end)(rl)
return
end
diff --git a/base/special/trig.jl b/base/special/trig.jl
index 8b78397..92c1d5a 100644
--- a/base/special/trig.jl
+++ b/base/special/trig.jl
@@ -299,12 +299,12 @@ end
7.81794442939557092300e-05, # T10
-1.85586374855275456654e-05) # T12
v = y² * @horner(y⁴,
- 5.39682539762260521377e-02, # T3
- 8.86323982359930005737e-03, # T5
- 1.45620945432529025516e-03, # T7
- 2.46463134818469906812e-04, # T9
- 7.14072491382608190305e-05, # T11
- 2.59073051863633712884e-05) # T13
+ 5.39682539762260521377e-02, # T3
+ 8.86323982359930005737e-03, # T5
+ 1.45620945432529025516e-03, # T7
+ 2.46463134818469906812e-04, # T9
+ 7.14072491382608190305e-05, # T11
+ 2.59073051863633712884e-05) # T13
# Precompute y³
y³ = y² * yhi
# Calculate P(y)-y-T1*y³ = y⁵*r + y⁵*v = y²(y³*(r+v))
diff --git a/stdlib/FileWatching/test/runtests.jl b/stdlib/FileWatching/test/runtests.jl
index d1694d7..e58c261 100644
--- a/stdlib/FileWatching/test/runtests.jl
+++ b/stdlib/FileWatching/test/runtests.jl
@@ -423,7 +423,7 @@ using Base.Filesystem: StatStruct
@test pop!(changes) == ("" => FileWatching.FileEvent())
if F_GETPATH
Sys.iswindows() && @test pop!(changes) ==
- (F_PATH => FileWatching.FileEvent(FileWatching.UV_CHANGE))
+ (F_PATH => FileWatching.FileEvent(FileWatching.UV_CHANGE))
p = pop!(changes)
if !Sys.isapple()
@test p == (F_PATH => FileWatching.FileEvent(FileWatching.UV_RENAME))
diff --git a/stdlib/InteractiveUtils/src/clipboard.jl b/stdlib/InteractiveUtils/src/clipboard.jl
index 1bcf539..a0058d1 100644
--- a/stdlib/InteractiveUtils/src/clipboard.jl
+++ b/stdlib/InteractiveUtils/src/clipboard.jl
@@ -123,7 +123,7 @@ elseif Sys.iswindows()
Base.windowserror(:CloseClipboard) # this should never fail
end
if cause !== :success && !(cause === :GetClipboardData &&
- (errno == 0x8004006A || errno == 0x800401D3)) # ignore DV_E_CLIPFORMAT and CLIPBRD_E_BAD_DATA from GetClipboardData
+ (errno == 0x8004006A || errno == 0x800401D3)) # ignore DV_E_CLIPFORMAT and CLIPBRD_E_BAD_DATA from GetClipboardData
Base.windowserror(cause, errno)
end
return ""
diff --git a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl
index 55b5a9e..0c8c9bd 100644
--- a/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl
+++ b/stdlib/REPL/src/TerminalMenus/AbstractMenu.jl
@@ -192,7 +192,7 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu;
true
catch err
suppress_output || @warn "TerminalMenus: Unable to enter raw mode: " exception=(err,
- catch_backtrace())
+ catch_backtrace())
false
end
# hide the cursor
diff --git a/stdlib/Random/src/Xoshiro.jl b/stdlib/Random/src/Xoshiro.jl
index b720092..0b453f6 100644
--- a/stdlib/Random/src/Xoshiro.jl
+++ b/stdlib/Random/src/Xoshiro.jl
@@ -323,7 +323,7 @@ for FT in (Float16, Float32, Float64)
# Float32(i >>> 8) * Float32(0x1.0p-24)
# Float32(i >>> 11) * Float64(0x1.0p-53)
@eval @inline _uint2float(i::$(UT), ::Type{$(FT)}) = $(FT)(i >>> $(8 * sizeof(FT) -
- precision(FT))) *
+ precision(FT))) *
$(FT(2) ^ -precision(FT))
@eval rand(r::Union{TaskLocalRNG,Xoshiro}, ::SamplerTrivial{CloseOpen01{$(FT)}}) = _uint2float(rand(r,
diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl
index b76fb57..5b85834 100644
--- a/stdlib/Test/src/Test.jl
+++ b/stdlib/Test/src/Test.jl
@@ -64,8 +64,8 @@ function test_callsite(bt, file_ts, file_t)
# The order will always be <internal functions> -> `@test` -> `@testset`.
internal = @something(macrocall_location(bt, @__FILE__), return nothing)
test = internal - 1 + @something(findfirst(ip -> any(frame -> in_file(frame, file_t),
- StackTraces.lookup(ip)), @view bt[internal:end]),
- return nothing)
+ StackTraces.lookup(ip)), @view bt[internal:end]),
+ return nothing)
testset = test - 1 +
@something(macrocall_location(@view(bt[test:end]), file_ts), return nothing)
diff --git a/test/arrayops.jl b/test/arrayops.jl
index 02e110b..a376b61 100644
--- a/test/arrayops.jl
+++ b/test/arrayops.jl
@@ -1986,7 +1986,7 @@ for N in 1:Nmax
# Indexing with (UnitRange, UnitRange, Int)
args = ntuple(d->d<N ? UnitRange{Int} : Int, N)
N > 1 && @test Base.return_types(getindex, Tuple{Array{Float32,N},args...}) ==
- [Array{Float32,N-1}]
+ [Array{Float32,N-1}]
N > 1 &&
@test Base.return_types(getindex, Tuple{BitArray{N},args...}) == [BitArray{N-1}]
N > 1 &&
diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl
index 60283a4..c95ad96 100644
--- a/test/cmdlineargs.jl
+++ b/test/cmdlineargs.jl
@@ -290,7 +290,7 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no`
@test tempdir() ==
readchomp(`$exename --project=@temp -e 'println(Base.active_project())'`)[1:lastindex(tempdir())]
@test tempdir() == readchomp(addenv(`$exename -e 'println(Base.active_project())'`,
- "JULIA_PROJECT" => "@temp", "HOME" => homedir()))[1:lastindex(tempdir())]
+ "JULIA_PROJECT" => "@temp", "HOME" => homedir()))[1:lastindex(tempdir())]
# --quiet, --banner
let p = "print((Base.JLOptions().quiet, Base.JLOptions().banner))"
diff --git a/test/subtype.jl b/test/subtype.jl
index a89f613..7b3dbc4 100644
--- a/test/subtype.jl
+++ b/test/subtype.jl
@@ -2622,7 +2622,7 @@ let S = Tuple{Val{T},T} where {S1,T<:Val{Union{Nothing,S1}}},
@testintersect(S, T, !Union{})
# not ideal (`S1` should be unbounded)
@test_broken testintersect(S, T) == Tuple{Val{Val{Union{Nothing,S1}}},
- Val{Union{Nothing,S1}}} where {S1<:(Union{Nothing,S2} where S2)}
+ Val{Union{Nothing,S1}}} where {S1<:(Union{Nothing,S2} where S2)}
end
#issue #47874:case1
@@ -2901,7 +2901,7 @@ let T = Tuple{Union{Type{T},Type{S}},Union{Val{T},Val{S}},
@test typeintersect(T, S) ==
Tuple{Type{T},Union{Val{T},Val{S}},Val{T}} where {S<:Val,T<:Val}
@test typeintersect(S, T) == Tuple{Type{T},Union{Val{T},Val{S}},
- Val{T}} where {T<:Val,S<:(Union{Val{A},Val} where A)}
+ Val{T}} where {T<:Val,S<:(Union{Val{A},Val} where A)}
end
#issue #49857
|
|
Most of those are fine. I still sense there are problems ....... .ugh |
Closes #1230
Claude wrote this
Claude spam
YAS: misaligned continuation lines after un-nesting a binary op
Symptom
33333333333333333333should line up with1111111111111111111111at column 19. It comesout at column 10 instead.
Two other right-hand sides are affected the same way — a unary operator applied to a
bracketed expression, and a
where:The mechanism
The relevant code is
n_binaryopcall!insrc/styles/default/nest.jl. The bug is in howit undoes a nesting decision it made speculatively.
To lay out
x in @mymacro [111…, 222…, 333…, 444…]at margin 92:The whole thing is 97 wide, so it nests at the operator, putting the RHS on its own
line.
inis not an assignment, soindent_nestis false and the RHS is placed atfst.indent— column 4, the loop-body indent.The RHS is nested there. A
MacroBlockhas no nest function of its own, so it hitsthe generic fallback, which walks
@(1) +mymacro(7) +(1) and nests theVectatcolumn 13.
n_tuple!then setsVect.indent = 13 + 1 = 14— align just past the[.The LHS is nested, and the code re-measures: does the RHS's first line fit after
for x in?9 + 59 + 1 = 69 ≤ 92, so yes — the nesting was unnecessary and getsundone.
fst[i1] = Whitespace(1),fst[i2] = Whitespace(0), and the RHS goes back on the sameline, now starting at column 9 rather than 4.
The RHS has moved sideways by +5, but everything inside it was aligned for column 4.
The undo is a heuristic
Step 4 calls
walk(unnest!(style; dedent = true), rhs, s), anddedent!(
src/nest_utils.jl) simply subtracts one indent level from every non-leaf:Vect.indentgoes 14 → 10.That is the right move for constructs indented from the start of the line: a block body
genuinely shifts left by one level when a level of nesting disappears. It is meaningless
for content aligned against a bracket, which has to move by however far the RHS actually
moved — here +5, to column 19 — not by −4.
The repair step, and why it only worked sometimes
The old code knew this and patched it up afterwards, but only for two node types:
is_unnamed_iterablecoversTupleN, Vect, Vcat, Ncat, Braces, Comprehension, Brackets;is_named_iterablecoversCall, Curly, TypedComprehension, MacroCall, RefN, TypedVcat, TypedNcat. AMacroBlockis in neither list, so no branch fired andVect.indentkeptthe raw dedent value of 10. Likewise for
UnaryandWhere.Why it had to be written per-type
The two formulas look different but are the same computation. Write
rhs_startfor thecolumn the RHS occupied in the nested layout:
unnamed iterable —
n_tuple!had setrhs.indent = rhs_start + 1, so after thededent it is
rhs_start + 1 - indent, andnamed iterable —
n_call!had setrhs.indent = rhs_start + len(name) + 1when itreached the opener, and
length(rhs[1]) + length(rhs[2])islen(name) + 1, soBoth reduce to
line_offset - rhs_start + s.opts.indent: how far the RHS moved, plusundo the dedent.
Neither branch had
rhs_startto hand, so each one reconstructed it backwards out ofrhs.indent— which only works if you already know exactly how that node type's nestfunction assigned
indent. That is the whole reason there had to be one branch per type,and the reason for the
+ 1and+ length(rhs[1]) + length(rhs[2])fudge factors: theyare the offset from the node's start column to its alignment column, cancelling out the
same offset baked into
rhs.indent.So the bug was structural rather than an oversight about one node type. Any RHS whose nest
function sets
indentby a rule not enumerated in those two branches gets no repair at alland silently keeps the dedent.
The fix
Record
rhs_startdirectly, captured immediately before the RHS is nested:and then apply the single shift:
No reverse-engineering, and the per-type fudge factors disappear. The existing iterable
cases are unchanged, since the old formulas were algebraically equal to this one.
What remains is the one question that genuinely is per-type, and which the old code was
conflating with the arithmetic: does this node align to its own starting column at all,
or to the start of the line? That is
is_column_aligned(src/fst.jl):The distinction is real, not defensive: a first attempt applied the shift unconditionally
and broke the existing
ccc => function () … endtest, because a long-form function bodyis line-anchored and the plain dedent was already correct for it. For the same reason a
MacroBlockdelegates to its final argument —@testset "x" begin … endmust not move,@mymacro [a, b]must.Which node types can be affected
Only right-hand sides that (a) reach the un-nest path while still spanning several lines
and (b) are column-aligned.
Binary,Chain,ComparisonandConditionalare column-aligned in YAS but cannotqualify:
n_binaryopcall!adds their full width toline_marginbefore deciding toun-nest, so they only ever un-nest when they have collapsed onto a single line, at which
point there is no continuation line to misplace.
Note that
Unaryis excluded from that clause exactly when its operand is aBrackets—which is how the unary case became reachable.
Sweeping every
.jlfile in the repo with instrumentation on the un-nest path turned upMacroBlock,UnaryandWhereas the reachable cases (plusStringN, whichunnest!skips, and
Begin, which is correctly line-anchored).An unrelated pre-existing bug found along the way
At tight margins the output is not idempotent — but this predates the fix and is not
specific to it. A plain
Vectright-hand side, which the old code already re-aligned,breaks the same way:
On the second pass the source already contains the line break, which changes how the RHS
is measured when deciding whether to un-nest. The regression tests were placed at margins
where the output is idempotent (
test_formatchecks this) rather than working around it.