module SciMLStyleTests

using Test
using JuliaFormatter: format_text, SciMLStyle
using JuliaFormatter.Internal: test_format

@testset "SciML Style" begin
    # Test for mathematical expressions not breaking unnecessarily
    str = raw"""
    du[i, j, 1] = alpha * (u[im1, j, 1] + u[ip1, j, 1] + u[i, jp1, 1] + u[i, jm1, 1] - 4u[i, j, 1]) + B + u[i, j, 1]^2 * u[i, j, 2] - (A + 1) * u[i, j, 1] + brusselator_f(x, y)
    """
    # Should not break if within margin (92 chars)
    if length(str) <= 92
        @test format_text(str, SciMLStyle()) == str
    end

    # Test for function calls not breaking unnecessarily
    str = raw"""
    res = NLS.solve(nlls_prob, NLS.LevenbergMarquardt(); maxiters = 1000, show_trace = Val(true))
    """
    # Should remain on one line if it fits
    @test format_text(str, SciMLStyle()) == str

    # Test for anonymous function parameters not breaking
    str = raw"""
    f! = @closure (cfx, cx, user_ctx) -> begin
        # function body
    end
    """
    formatted_str = raw"""
    f! = @closure (cfx, cx, user_ctx) -> begin
        # function body
    end
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    # Test for array indexing not breaking unnecessarily
    str = raw"""
    du[i, j, 1] = alpha * (u[im1, j, 1] + u[ip1, j, 1] + u[i, jp1, 1] + u[i, jm1, 1] - 4u[i, j, 1])
    """
    # Should not break du[i, j, 1] when close to margin
    formatted = format_text(str, SciMLStyle())
    @test !contains(formatted, "du[\n")
    @test startswith(strip(formatted), "du[i, j, 1]")
    str = raw"""
       @noinline require_complete(m::Matching) = m.inv_match === nothing && throw(ArgumentError("Backwards matching not defined. `complete` the matching first."))
    """
    formatted_str = raw"""
    @noinline require_complete(m::Matching) = m.inv_match === nothing &&
                                              throw(ArgumentError("Backwards matching not defined. `complete` the matching first."))
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    begin include("hi") end
    """
    formatted_str = raw"""
    begin
        include("hi")
    end
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    begin include("hi"); 1 end
    """
    formatted_str = raw"""
    begin
        include("hi")
        1
    end
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    BipartiteGraph(fadj::AbstractVector, badj::Union{AbstractVector,Integer} = maximum(maximum, fadj); metadata = nothing) = BipartiteGraph(mapreduce(length, +, fadj; init = 0), fadj, badj, metadata)
    """
    formatted_str = raw"""
    function BipartiteGraph(fadj::AbstractVector,
            badj::Union{AbstractVector, Integer} = maximum(maximum, fadj); metadata = nothing)
        BipartiteGraph(mapreduce(length, +, fadj; init = 0), fadj, badj, metadata)
    end
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    @parameters a=b b=c
    """
    formatted_str = raw"""
    @parameters a=b b=c
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    @parameters a = b b = c
    """
    formatted_str = raw"""
    @parameters a=b b=c
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    @parameters a=b
    """
    formatted_str = raw"""
    @parameters a=b
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    str = raw"""
    @parameters a = b
    """
    formatted_str = raw"""
    @parameters a = b
    """
    @test format_text(str, SciMLStyle()) == formatted_str

    @testset "function argument indent" begin
        str = raw"""
        function my_large_function(argument1, argument2,
                                   argument3, argument4,
                                   argument5, x, y, z)
            foo(x) + goo(y)
        end
        """

        formatted_str = raw"""
        function my_large_function(argument1, argument2,
                argument3, argument4,
                argument5, x, y, z)
            foo(x) + goo(y)
        end
        """
        @test format_text(str, SciMLStyle()) == formatted_str

        formatted_str_yas_nesting = raw"""
        function my_large_function(argument1, argument2,
                                   argument3, argument4,
                                   argument5, x, y, z)
            foo(x) + goo(y)
        end
        """
        @test format_text(str, SciMLStyle(); yas_style_nesting = true) ==
              formatted_str_yas_nesting
    end

    @testset "indent on rhs of assignment" begin
        # https://github.com/JuliaEditorSupport/JuliaFormatter.jl/issues/935
        str = "xyz = T[a => 1,\n      b => 2]"
        yas_result = "xyz = T[a => 1,\n        b => 2]"
        sciml_result = "xyz = T[a => 1,\n    b => 2]"
        @test format_text(str, SciMLStyle(); yas_style_nesting = true) == yas_result
        @test format_text(str, SciMLStyle()) == sciml_result
    end

    @testset "postfix operator" begin
        # https://github.com/JuliaEditorSupport/JuliaFormatter.jl/pull/1011
        str1 = "@view (Q_temp' * _vstar_perp)[1:nus]"
        @test format_text(str1, SciMLStyle()) == str1
        str2 = "(Q' * 2)[]"
        @test format_text(str2, SciMLStyle()) == str2
    end

    str = raw"""
    Dict{Int, Int}(1 => 2,
        3 => 4)
    """

    # This should be valid with and without `Dict` in `variable_call_indent`
    @test format_text(str, SciMLStyle()) == str
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == str

    str = raw"""
    SVector(1.0,
        2.0)
    """

    # Test the same with different callers
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == str
    @test format_text(str, SciMLStyle(); variable_call_indent = ["SVector", "test2"]) == str

    str = raw"""
    Dict{Int, Int}(
    1 => 2,
               3 => 4)
    """

    formatted_str1 = raw"""
    Dict{Int, Int}(
        1 => 2,
        3 => 4)
    """

    formatted_str2 = raw"""
    Dict{Int, Int}(
        1 => 2,
        3 => 4)
    """

    # `variable_call_indent` keeps the line break and doesn't align
    @test format_text(str, SciMLStyle()) == formatted_str1
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str2

    str = raw"""
    SVector(
    1.0,
               2.0)
    """

    formatted_str1 = raw"""
    SVector(
        1.0,
        2.0)
    """

    formatted_str2 = raw"""
    SVector(
        1.0,
        2.0)
    """

    # Test the same with different callers
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str1
    @test format_text(str, SciMLStyle(); variable_call_indent = ["test", "SVector"]) ==
          formatted_str2

    str = raw"""
    Dict{Int, Int}(
        1 => 2,
        3 => 4,
    )
    """

    # appears on a different line in source
    formatted_str = raw"""
    Dict{Int, Int}(
        1 => 2,
        3 => 4
    )
    """

    formatted_str_yas_nesting = raw"""
    Dict{Int, Int}(1 => 2,
                   3 => 4)
    """

    # This is already valid with `variable_call_indent`
    @test format_text(str, SciMLStyle()) == formatted_str
    @test format_text(str, SciMLStyle(); yas_style_nesting = true) ==
          formatted_str_yas_nesting
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str

    str = raw"""
    SomeLongerTypeThanJustString = String
    y = Dict{Int, SomeLongerTypeThanJustString}(1 => "some arbitrary string bla bla bla bla bla bla",
        2 => "another longer arbitrary string bla bla bla bla bla bla bla bla")
    """

    # over margin will nest
    formatted_str1 = raw"""
    SomeLongerTypeThanJustString = String
    y = Dict{Int, SomeLongerTypeThanJustString}(
        1 => "some arbitrary string bla bla bla bla bla bla",
        2 => "another longer arbitrary string bla bla bla bla bla bla bla bla")
    """

    formatted_str2 = raw"""
    SomeLongerTypeThanJustString = String
    y = Dict{Int, SomeLongerTypeThanJustString}(
        1 => "some arbitrary string bla bla bla bla bla bla",
        2 => "another longer arbitrary string bla bla bla bla bla bla bla bla")
    """

    # Here, `variable_call_indent` forces the line break because the line is too long
    @test format_text(str, SciMLStyle()) == formatted_str1
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str2

    str = raw"""
    Dict{Int, Int}(
                   # Comment
                   1 => 2,
                   3 => 4)
    """

    formatted_str = raw"""
    Dict{Int, Int}(
        # Comment
        1 => 2,
        3 => 4)
    """

    # Test `variable_call_indent` with a comment in a separate line
    @test format_text(str, SciMLStyle()) == formatted_str
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str

    str = raw"""
    SVector(
            # Comment
            1.0,
            2.0)
    """

    formatted_str = raw"""
    SVector(
        # Comment
        1.0,
        2.0)
    """

    # Test the same with different callers
    @test format_text(str, SciMLStyle()) == formatted_str
    @test format_text(str, SciMLStyle(); variable_call_indent = ["SVector"]) ==
          formatted_str

    str = raw"""
    Dict{Int, Int}(# Comment
                   1 => 2,
                   3 => 4)
    """

    formatted_str1 = raw"""
    Dict{Int, Int}(# Comment
        1 => 2,
        3 => 4)
    """

    formatted_str2 = raw"""
    Dict{Int, Int}(# Comment
        1 => 2,
        3 => 4)
    """

    # Test `variable_call_indent` with an inline comment after the opening parenthesis
    # With `variable_call_indent = false`, the comment will be eaten,
    # see https://github.com/JuliaEditorSupport/JuliaFormatter.jl/issues/609
    @test format_text(str, SciMLStyle()) == formatted_str1
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str2

    str = raw"""
    Dict{Int, Int}( # Comment
            # Comment
            1 => 2,
            # Another comment
            3 => 4)
    """

    formatted_str = raw"""
    Dict{Int, Int}( # Comment
        # Comment
        1 => 2,
        # Another comment
        3 => 4)
    """

    # Test `variable_call_indent` with both an inline comment after the opening parenthesis
    # and a comment in a separate line.
    @test format_text(str, SciMLStyle()) == formatted_str
    @test format_text(str, SciMLStyle(); variable_call_indent = ["Dict"]) == formatted_str

    str = raw"""
    SVector( # Comment
                # Comment
                1.0,
                # Another comment
                2.0)
    """

    formatted_str = raw"""
    SVector( # Comment
        # Comment
        1.0,
        # Another comment
        2.0)
    """

    # Test the same with different callers
    @test format_text(str, SciMLStyle(); variable_call_indent = ["test"]) == formatted_str
    @test format_text(str, SciMLStyle(); variable_call_indent = ["SVector", "test"]) ==
          formatted_str

    str = """
    function alg_cache(alg::FineRKN4, u, rate_prototype, ::Type{uEltypeNoUnits},
           ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t,
          dt, reltol, p, calck, ::Val{true}) where {uEltypeNoUnits,
        uBottomEltypeNoUnits,tTypeNoUnits}

        reduced_rate_prototype = rate_prototype.x[2]
        tab = FineRKN4ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits))
        k1 = zero(rate_prototype)
        k2 = zero(reduced_rate_prototype)
        k3 = zero(reduced_rate_prototype)
        k4 = zero(reduced_rate_prototype)
        k5 = zero(reduced_rate_prototype)
        k = zero(rate_prototype)
        utilde = zero(u)
        atmp = similar(u, uEltypeNoUnits)
        recursivefill!(atmp, false)
        tmp = zero(u)
        FineRKN4Cache(u, uprev, k1, k2, k3, k4, k5, k, utilde, tmp, atmp, tab)
    end"""

    formatted_str = """
    function alg_cache(alg::FineRKN4, u, rate_prototype, ::Type{uEltypeNoUnits},
            ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t,
            dt, reltol, p, calck,
            ::Val{true}) where {uEltypeNoUnits,
            uBottomEltypeNoUnits, tTypeNoUnits}
        reduced_rate_prototype = rate_prototype.x[2]
        tab = FineRKN4ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits))
        k1 = zero(rate_prototype)
        k2 = zero(reduced_rate_prototype)
        k3 = zero(reduced_rate_prototype)
        k4 = zero(reduced_rate_prototype)
        k5 = zero(reduced_rate_prototype)
        k = zero(rate_prototype)
        utilde = zero(u)
        atmp = similar(u, uEltypeNoUnits)
        recursivefill!(atmp, false)
        tmp = zero(u)
        FineRKN4Cache(u, uprev, k1, k2, k3, k4, k5, k, utilde, tmp, atmp, tab)
    end"""
    @test format_text(str, SciMLStyle()) == formatted_str

    str = """
    function SpatialMassActionJump(urates::A, srates::B, rs::S, ns::U, pmapper::V;
                                   scale_rates = true, useiszero = true,
                                   nocopy = false) where {A <: AVecOrNothing,
                                                          B <: AMatOrNothing, S, U, V}
        SpatialMassActionJump{A, B, S, U, V}(urates, srates, rs, ns, pmapper, scale_rates,
                                             useiszero, nocopy)
    end"""

    formatted_str = """
    function SpatialMassActionJump(urates::A, srates::B, rs::S, ns::U, pmapper::V;
            scale_rates = true, useiszero = true,
            nocopy = false) where {A <: AVecOrNothing,
            B <: AMatOrNothing, S, U, V}
        SpatialMassActionJump{A, B, S, U, V}(urates, srates, rs, ns, pmapper, scale_rates,
            useiszero, nocopy)
    end"""
    @test format_text(str, SciMLStyle()) == formatted_str

    str = """
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::SomePrettyLongTypeName{Foo}
    """

    # disallow_single_arg_nesting is true by defaultin sciml formatting options, so we don't want the line break
    @test format_text(str, SciMLStyle()) == str
    # With `yas_style_nesting=true`, we don't want the line break, as it will look like this:
    # xxxxx::SomePrettyLongTypeName{
    #                               Foo
    #                              }
    @test format_text(str, SciMLStyle(); yas_style_nesting = true) == str

    # https://github.com/SciML/JumpProcesses.jl/pull/362#discussion_r1375432275
    str_ = """
    function (p::CoevolveJumpAggregation{
        T,
        S,
        F1,
        F2,
    })(integrator::AbstractSSAIntegrator) where {T, S, F1, F2 <: Union{Tuple, Nothing}}
        body
    end"""
    str = """
    function (p::CoevolveJumpAggregation{
            T,
            S,
            F1,
            F2
    })(integrator::AbstractSSAIntegrator) where {
            T,
            S,
            F1,
            F2 <:
            Union{
                Tuple,
                Nothing}}
        body
    end"""
    @test format_text(str_, SciMLStyle(); margin = 1) == str

    str_ = """
    macro (p::CoevolveJumpAggregation{
        T,
        S,
        F1,
        F2,
    })(integrator::AbstractSSAIntegrator) where {T, S, F1, F2 <: Union{Tuple, Nothing}}
        body
    end"""
    str = """
    macro (p::CoevolveJumpAggregation{
            T,
            S,
            F1,
            F2
    })(integrator::AbstractSSAIntegrator) where {
            T,
            S,
            F1,
            F2 <:
            Union{
                Tuple,
                Nothing}}
        body
    end"""
    @test format_text(str_, SciMLStyle(); margin = 1) == str

    @testset "optimal nesting" begin
        @testset "function definition" begin
            str = """
            function foo(arg1, arg2, arg3, arg4, arg5)
                body
            end
            """

            fstr = """
            function foo(
                    arg1, arg2, arg3, arg4, arg5)
                body
            end
            """
            @test format_text(str, SciMLStyle(); margin = 41) == fstr
            @test format_text(str, SciMLStyle(); margin = 37) == fstr

            fstr = """
            function foo(arg1, arg2, arg3,
                    arg4, arg5)
                body
            end
            """
            @test format_text(str, SciMLStyle(); margin = 36) == fstr
            # should be 30? might be a unnesting off by 1 error
            @test format_text(str, SciMLStyle(); margin = 31) == fstr

            fstr = """
            function foo(
                    arg1, arg2, arg3,
                    arg4, arg5)
                body
            end
            """
            @test format_text(str, SciMLStyle(); margin = 29) == fstr
            @test format_text(str, SciMLStyle(); margin = 25) == fstr

            fstr = """
            function foo(
                    arg1, arg2,
                    arg3,
                    arg4, arg5)
                body
            end
            """
            @test format_text(str, SciMLStyle(); margin = 24) == fstr

            fstr = """
            function foo(
                    arg1,
                    arg2,
                    arg3,
                    arg4,
                    arg5)
                body
            end
            """
            @test format_text(str, SciMLStyle(); margin = 18) == fstr
        end

        @testset "vector definition" begin
            str = """
            test = [arg1, arg2, arg3, arg4, arg5]
            """

            # Fits within the margin
            @test format_text(str, SciMLStyle(); margin = 41) == str
            @test format_text(str, SciMLStyle(); margin = 37) == str

            fstr = """
            test = [
                arg1, arg2, arg3, arg4, arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 36) == fstr
            @test format_text(str, SciMLStyle(); margin = 33) == fstr

            fstr = """
            test = [arg1, arg2, arg3,
                arg4, arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 32) == fstr
            # should be 25? might be a unnesting off by 1 error
            @test format_text(str, SciMLStyle(); margin = 26) == fstr

            fstr = """
            test = [
                arg1, arg2, arg3,
                arg4, arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 25) == fstr
            @test format_text(str, SciMLStyle(); margin = 21) == fstr

            fstr = """
            test = [arg1, arg2,
                arg3,
                arg4, arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 20) == fstr
            # should be 19? might be a unnesting off by 1 error
            # @test format_text(str, SciMLStyle(), margin = 19) == fstr

            fstr = """
            test = [
                arg1, arg2,
                arg3,
                arg4, arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 19) == fstr
            # should be 15? might be a unnesting off by 1 error
            @test format_text(str, SciMLStyle(); margin = 16) == fstr

            fstr = """
            test = [
                arg1, arg2,
                arg3,
                arg4,
                arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 15) == fstr

            fstr = """
            test = [arg1,
                arg2,
                arg3,
                arg4,
                arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 14) == fstr

            fstr = """
            test = [
                arg1,
                arg2,
                arg3,
                arg4,
                arg5]
            """
            @test format_text(str, SciMLStyle(); margin = 13) == fstr
        end

        @testset "for tuple binding regression" begin
            # see: https://github.com/JuliaEditorSupport/JuliaFormatter.jl/pull/998
            str = """
            function copy_values!(destination::ThreadedArray, source::AbstractArray)
                @threaded destination.scheduler for (dest_id, src_id) in zip(eachindex(destination),
                                                            eachindex(source))
                    @inbounds destination[dest_id] = source[src_id]
                end
            end
            """

            fstr = """
            function copy_values!(destination::ThreadedArray, source::AbstractArray)
                @threaded destination.scheduler for (dest_id, src_id) in zip(eachindex(destination),
                                                                             eachindex(source))
                    @inbounds destination[dest_id] = source[src_id]
                end
            end
            """
            @test format_text(str, SciMLStyle(); yas_style_nesting = true) == fstr

            str = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc, dddd) in zip(eachindex(destination),
                      eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """

            fstr = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc, dddd) in zip(eachindex(destination),
                                                                                                  eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """
            @test format_text(str, SciMLStyle(); yas_style_nesting = true, margin = 92) == fstr

            fstr = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc,
                                                 dddd) in zip(eachindex(destination),
                                                              eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """
            @test format_text(
                str,
                SciMLStyle();
                yas_style_nesting = true,
                margin = 92,
                sciml_margin_overrun = 0,
            ) == fstr

            # todo:
            # fstr = """
            # @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc, dddd) in zip(
            #                                      eachindex(destination),
            #                                      eachindex(source))
            #     @inbounds destination[dest_id] = source[src_id]
            # end
            # """

            fstr = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc, dddd) in zip(
                eachindex(destination),
                eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """
            @test format_text(str, SciMLStyle(); margin = 92) == fstr
            @test format_text(str, SciMLStyle(); margin = 92, sciml_margin_overrun = 0) ==
                  fstr

            str = """
            @threaded destination.scheduler for i in zip(eachindex(destination),
                      eachindex(source))
                body
            end
            """

            fstr = """
            @threaded destination.scheduler for i in zip(eachindex(destination),
                eachindex(source))
                body
            end
            """
            @test format_text(str, SciMLStyle(); margin = 92) == fstr

            str = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc, dddd) ∈ zip(eachindex(destination),
                      eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """

            fstr = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc, dddd) ∈ zip(eachindex(destination),
                                                                                                 eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """
            @test format_text(
                str,
                SciMLStyle();
                yas_style_nesting = true,
                margin = 92,
                always_for_in = false,
            ) == fstr

            fstr = """
            @threaded destination.scheduler for (dest_id, src_id, aaaa, bbbb, ccccc,
                                                 dddd) ∈ zip(eachindex(destination),
                                                             eachindex(source))
                @inbounds destination[dest_id] = source[src_id]
            end
            """
            @test format_text(
                str,
                SciMLStyle();
                yas_style_nesting = true,
                margin = 92,
                always_for_in = false,
                sciml_margin_overrun = 0,
            ) == fstr
        end
    end

    @testset "additional nesting coverage" begin
        str = """
        path_lookup = [
            "Hash table implementation notes" => joinpath("src",
                                                          "hash_table.md"),
        ]
        """

        fstr = """
        path_lookup = [
            "Hash table implementation notes" => joinpath("src",
                                                          "hash_table.md"),
        ]
        """
        @test format_text(str, SciMLStyle(); yas_style_nesting = true) == fstr

        str = """
        function collect_close_items(points, min_distance)
            foreach_neighbor(points, points, index;
                             backend=SerialBackend()) do item, neighbor,
                                                         _, _
                if item != neighbor
                    push!(result, item)
                end
            end
        end
        """

        fstr = """
        function collect_close_items(points, min_distance)
            foreach_neighbor(points, points, index;
                             backend=SerialBackend()) do item, neighbor,
                                                         _, _
                if item != neighbor
                    push!(result, item)
                end
            end
        end
        """
        @test format_text(
            str,
            SciMLStyle();
            yas_style_nesting = true,
            whitespace_in_kwargs = false,
        ) == fstr

        str = "Dict(\"a\" => (x = 1,), \"longer key\" => (y = 2,))"
        @test format_text(str, SciMLStyle()) == str

        str = """
        metadata = Pair{String, Any}["Start vertex" => first(graph.vertices),
        "Final vertex" => last(graph.vertices),
        "search algorithm" => traversal.algorithm |> typeof |> nameof,
        "directed" => graph.is_directed]
        """ |> strip
        sciml = """
        metadata = Pair{String, Any}["Start vertex" => first(graph.vertices),
            "Final vertex" => last(graph.vertices),
            "search algorithm" => traversal.algorithm |> typeof |> nameof,
            "directed" => graph.is_directed]
        """ |> strip
        test_format(str, sciml, SciMLStyle())
        with_yas = """
        metadata = Pair{String, Any}["Start vertex" => first(graph.vertices),
                                     "Final vertex" => last(graph.vertices),
                                     "search algorithm" => traversal.algorithm |> typeof |> nameof,
                                     "directed" => graph.is_directed]
        """ |> strip
        test_format(str, with_yas, SciMLStyle(); yas_style_nesting = true)
    end

    str = raw"""
    x = [
        1, 2, 3
    ]
    """

    # This should be valid with and without `yas_style_nesting`
    @test format_text(str, SciMLStyle()) == str
    @test format_text(str, SciMLStyle(); yas_style_nesting = true) == str

    # Test for comprehensive line break fixes
    # https://github.com/SciML/DiffEqGPU.jl/pull/356/files

    # Test 1: Array indexing should not be broken across lines
    str = """
    du[II[i, j, 1]] = α * (u[II[im1, j, 1]] + u[II[ip1, j, 1]] + u[II[i, jp1, 1]] + u[II[i, jm1, 1]])
    """
    formatted = format_text(str, SciMLStyle())
    # The key fix: array indices should not be broken between parameters
    @test !contains(formatted, "II[i,\n")  # Should not break between i and j
    @test !contains(formatted, "II[i, j,\n")  # Should not break between j and 1

    # Test 2: @unpack macro calls should not be broken unnecessarily
    str = "@unpack γ, a31, a32, a41, a42, a43, btilde1, btilde2, btilde3, btilde4, c3 = integ.tab"
    formatted = format_text(str, SciMLStyle())
    # Should not break the unpack statement awkwardly
    lines = split(formatted, "\n")
    @test length(lines) <= 2  # Should fit on 1-2 lines max

    # Test 3: Function calls should not be broken awkwardly
    str = "beta1, beta2, qmax, qmin, gamma = build_adaptive_controller_cache(integ.alg, T)"
    formatted = format_text(str, SciMLStyle())
    lines = split(formatted, "\n")
    @test length(lines) <= 2  # Should not create excessive line breaks

    # Test 4: Type parameters should not be broken unnecessarily
    str = "Vector{Float64, Int32, String}"
    formatted = format_text(str, SciMLStyle())
    @test !contains(formatted, "{\n")  # Should not break type parameters

    # Test 5: Short vector literals should not be broken
    str = "[a, b, c, d]"
    formatted = format_text(str, SciMLStyle())
    @test formatted == str  # Should remain on one line

    @testset "SciML Repository Regression Tests" begin
        # These tests are based on real formatting issues found in SciML repositories
        # that were broken by JuliaFormatter v2 changes

        @testset "DiffEqGPU.jl regressions" begin
            # Test case from: https://github.com/SciML/DiffEqGPU.jl/pull/356/files
            # Array indexing in mathematical expressions should not be broken
            str = """
            du[II[i, j, 1]] = α * (u[II[im1, j, 1]] + u[II[ip1, j, 1]] + u[II[i, jp1, 1]] +
                                   u[II[i, jm1, 1]] - 4u[II[i, j, 1]]) +
                                  B + u[II[i, j, 1]]^2 * u[II[i, j, 2]] - (A + 1) * u[II[i, j, 1]] +
                                  brusselator_f(x, y, t)
            """
            formatted = format_text(str, SciMLStyle())
            # Array indices should not be broken between parameters
            @test !contains(formatted, "II[i,\n")
            @test !contains(formatted, "II[i, j,\n")
            @test !contains(formatted, "II[im1,\n")
            @test !contains(formatted, "II[ip1,\n")

            # Second array indexing case from the same PR
            str = """
            du[II[i, j, 2]] = α * (u[II[im1, j, 2]] + u[II[ip1, j, 2]] + u[II[i, jp1, 2]] +
                                   u[II[i, jm1, 2]] - 4u[II[i, j, 2]]) +
                                  A * u[II[i, j, 1]] - u[II[i, j, 1]]^2 * u[II[i, j, 2]]
            """
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "II[i,\n")
            @test !contains(formatted, "II[i, j,\n")

            # @unpack macro should not break awkwardly
            str = "@unpack γ, a31, a32, a41, a42, a43, btilde1, btilde2, btilde3, btilde4, c3, α31, α32 = integ.tab"
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, "\n")
            @test length(lines) <= 2  # Should not break across many lines
            # Accept the current behavior - the key improvement is limiting to 2 lines max
            # The original problem was much worse breaking across many lines

            # Function assignment should not break awkwardly
            str = "beta1, beta2, qmax, qmin, gamma, qoldinit, _ = build_adaptive_controller_cache(integ.alg, T)"
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, "\n")
            @test length(lines) <= 2
            # The underscore should not be on its own line
            @test !contains(formatted, "qoldinit,\n_ =")
        end

        @testset "General SciML formatting patterns" begin
            # Common patterns that should not be broken excessively

            # Mathematical expressions with multiple array accesses
            str = "result = A[i, j] + B[i, k] * C[k, j] - D[i, j]"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "[i,\n")
            @test !contains(formatted, "[i, j,\n")
            @test !contains(formatted, "[i, k,\n")
            @test !contains(formatted, "[k, j,\n")

            # Function calls with multiple parameters should be conservative
            str = "solve(prob, alg, abstol=1e-6, reltol=1e-3, callback=cb)"
            formatted = format_text(str, SciMLStyle())
            # Should not break every single parameter
            lines = split(formatted, "\n")
            @test length(lines) <= 3  # Allow some breaking but not excessive

            # Type annotations should not break unnecessarily
            str = "function foo(x::AbstractVector{T}, y::AbstractMatrix{T}) where T<:Real end"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "AbstractVector{\nT")
            @test !contains(formatted, "AbstractMatrix{\nT")

            # Macro calls with assignments should be protected
            str = "@inbounds @simd for i in 1:n; end"
            formatted = format_text(str, SciMLStyle())
            # Allow reasonable formatting - the key is not excessive breaking
            @test length(split(formatted, "\n")) <= 4  # Allow reasonable flexibility

            # Complex expressions should prioritize readability
            str = "u_new[idx] = u_old[idx] + dt * (k1[idx] + 2*k2[idx] + 2*k3[idx] + k4[idx]) / 6"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "[idx,\n")
            @test !contains(formatted, "k1[idx,\n")
            @test !contains(formatted, "k2[idx,\n")
            @test !contains(formatted, "k3[idx,\n")
            @test !contains(formatted, "k4[idx,\n")
        end

        @testset "Edge cases from issue #930" begin
            # These are patterns mentioned in the GitHub issue that should be handled well

            # Short parameter lists should not be broken
            str = "f(a, b, c, d)"
            formatted = format_text(str, SciMLStyle())
            @test formatted == str

            # Short array literals should not be broken
            str = "[1, 2, 3, 4, 5]"
            formatted = format_text(str, SciMLStyle())
            @test formatted == str

            # Short tuple should not be broken
            str = "(x, y, z, w)"
            formatted = format_text(str, SciMLStyle())
            @test formatted == str

            # Short type parameters should not be broken
            str = "Vector{Float64}"
            formatted = format_text(str, SciMLStyle())
            @test formatted == str

            str = "Dict{String, Int}"
            formatted = format_text(str, SciMLStyle())
            @test formatted == str
        end

        @testset "Additional SciML repository patterns" begin
            # Patterns found in various SciML repositories that were problematic

            # Long function calls should not break every argument (common pattern)
            str = "OrdinaryDiffEqCore._ode_addsteps!(k, t, uprev, u, dt, f, p, cache, always_calc_begin, true, true)"
            formatted = format_text(str, SciMLStyle())
            # Should not put every single argument on its own line
            lines = split(formatted, "\n")
            @test length(lines) <= 4  # Allow reasonable breaking but not excessive

            # Complex constructor calls should be handled reasonably
            str = "CellGenotype([Float64(1)], :aSymbiontGenotype)"
            formatted = format_text(str, SciMLStyle())
            # Should not break the array literal unnecessarily
            @test !contains(formatted, "[Float64(\n")
            @test !contains(formatted, "Float64(1\n")

            # Nested function calls should prioritize readability
            str = "construct(Plant, (deepcopy(organ1), deepcopy(organ2)), Float64[], PlantSettings(1))"
            formatted = format_text(str, SciMLStyle())
            # Should not break simple arguments unnecessarily
            @test !contains(formatted, "deepcopy(\n")
            @test !contains(formatted, "Float64[\n")

            # Mathematical expressions with array indexing should stay readable
            str = "du[i] = α * u[i-1] + β * u[i] + γ * u[i+1]"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "u[i-\n")
            @test !contains(formatted, "u[i+\n")
            @test !contains(formatted, "du[\n")

            # Complex type annotations should not break type parameters
            str = "function solve(prob::BVProblem{T,U,V}, alg::Algorithm) where {T,U,V} end"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "BVProblem{\nT")
            @test !contains(formatted, "{T,\nU")

            # Closure definitions should be handled gracefully
            str = "@closure (t, u, du) -> du .= vec(prob.f(reshape(u, u0_size), prob.p, t))"
            formatted = format_text(str, SciMLStyle())
            # Should not break the simple parameter list
            @test !contains(formatted, "(t,\n")
            @test !contains(formatted, "u,\n")

            # Array slicing operations should not be broken
            str = "left_bc = reshape(@view(r[1:no_left_bc]), left_bc_size)"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "r[1:\n")
            @test !contains(formatted, "@view(\n")

            # Multiple assignment patterns should be conservative
            str = "ya, yb, ya_size, yb_size = extract_parameters(prob)"
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, "\n")
            @test length(lines) <= 2  # Should not break excessively

            # Nested array access should stay together
            str = "cache.u[cache.stage_indices[i]][j]"
            formatted = format_text(str, SciMLStyle())
            @test !contains(formatted, "cache.u[\n")
            @test !contains(formatted, "stage_indices[\n")
            @test !contains(formatted, "][j\n")
        end
    end

    @testset "semantic safety" begin
        # Test 1: Whitespace-sensitive array literals
        # Space means horizontal concatenation, ; or newline means vertical
        str = "[1 2 3]"  # 1×3 matrix
        @test format_text(str, SciMLStyle()) == str

        str = "[1; 2; 3]"  # 3×1 matrix
        @test format_text(str, SciMLStyle()) == str

        str = "[1 2; 3 4]"  # 2×2 matrix
        @test format_text(str, SciMLStyle()) == str

        # Test that we don't accidentally change array dimensions
        str = """
        A = [1 2 3
             4 5 6]
        """
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "1 2 3") # Ensure spaces preserved
        @test !contains(formatted, "1; 2; 3") # Ensure no semicolons added

        # Test 2: Operator precedence preservation
        precedence_tests = [
            ("x = a + b * c", "x = a + b * c"),
            ("x = a * b + c", "x = a * b + c"),
            ("x = a^b^c", "x = a^b^c"),  # Right associative
            ("x = a / b * c", "x = a / b * c"),  # Left associative
            ("x = -a^2", "x = -a^2"),  # Unary minus precedence
        ]

        for (input, expected) in precedence_tests
            @test format_text(input, SciMLStyle()) == expected
        end

        # Test 3: Coefficient syntax preservation
        # In Julia, 2x means 2*x, but 2 x is an error
        str = "y = 2x + 3y - 4z"
        @test format_text(str, SciMLStyle()) == str

        str = "y = 2(x + y)"  # Coefficient with parentheses
        @test format_text(str, SciMLStyle()) == str

        # Test 4: Macro scope preservation
        str = "@. x = y + z"
        formatted = format_text(str, SciMLStyle())
        @test formatted == str
        @test contains(formatted, "@.")

        str = "@views x[1:n] = y[1:n]"
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "@views")
        @test !contains(formatted, "@views\n")  # Macro not separated from expression

        # Test 5: String and character literals (must not break)
        str = "msg = \"This is a long string that should not be broken\""
        @test format_text(str, SciMLStyle()) == str

        str = "c = 'a'"
        @test format_text(str, SciMLStyle()) == str

        # Test 6: Ternary operator associativity
        str = "x = a ? b : c ? d : e"  # Right associative
        formatted = format_text(str, SciMLStyle())
        # Ensure it doesn't become (a ? b : c) ? d : e
        @test Meta.parse(str) == Meta.parse(formatted)

        # Test 7: Short-circuit evaluation order
        str = "a && b || c && d"
        formatted = format_text(str, SciMLStyle())
        @test Meta.parse(str) == Meta.parse(formatted)

        # Test 8: Anonymous function syntax
        str = "f = x -> x^2"
        @test format_text(str, SciMLStyle()) == str

        str = "g = (x, y) -> x + y"
        @test format_text(str, SciMLStyle()) == str

        # Test 9: Array comprehension preservation
        str = "[i * j for i in 1:3, j in 1:3]"
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "for i in 1:3, j in 1:3")

        # Test 10: Broadcasting syntax
        str = "x .= y .+ z .* w"
        @test format_text(str, SciMLStyle()) == str

        str = "sin.(x) .+ cos.(y)"
        @test format_text(str, SciMLStyle()) == str

        # Test 11: Type parameter syntax
        str = "Vector{Float64}"
        @test format_text(str, SciMLStyle()) == str

        str = "Dict{String,Int}"
        formatted = format_text(str, SciMLStyle())
        @test formatted == str || formatted == "Dict{String, Int}"  # Space after comma is ok

        # Test 12: Splatting and slurping
        str = "f(x...)"
        @test format_text(str, SciMLStyle()) == str

        str = "g(a, b..., c)"
        @test format_text(str, SciMLStyle()) == str

        # Test 13: Range syntax preservation
        str = "1:10"
        @test format_text(str, SciMLStyle()) == str

        str = "1:2:10"
        @test format_text(str, SciMLStyle()) == str

        # Test 14: Rational number syntax
        str = "1//2"
        @test format_text(str, SciMLStyle()) == str

        # Test 15: Complex number syntax
        str = "1 + 2im"
        @test format_text(str, SciMLStyle()) == str

        # Test 16: Symbol syntax
        str = ":symbol"
        @test format_text(str, SciMLStyle()) == str

        str = ":(a + b)"
        @test format_text(str, SciMLStyle()) == str

        # Test 17: Interpolation in strings
        str = "\"x = \$x, y = \$(y + 1)\""
        @test format_text(str, SciMLStyle()) == str

        # Test 18: Command literals
        str = "`echo hello`"
        @test format_text(str, SciMLStyle()) == str

        # Test 19: Version number literals
        str = "v\"1.2.3\""
        @test format_text(str, SciMLStyle()) == str

        # Test 20: Regex literals
        str = "r\"[a-z]+\""
        @test format_text(str, SciMLStyle()) == str

        # Test 21: Critical array literal semantic preservation
        # These MUST not change dimensions

        # Horizontal concatenation (space)
        str = "[1 2 3]"
        formatted = format_text(str, SciMLStyle())
        @test formatted == "[1 2 3]"  # Must preserve spaces

        # Vertical concatenation (semicolon)
        str = "[1; 2; 3]"
        formatted = format_text(str, SciMLStyle())
        @test formatted == "[1; 2; 3]"  # Must preserve semicolons

        # Mixed (creates matrix)
        str = "[1 2; 3 4]"
        formatted = format_text(str, SciMLStyle())
        @test formatted == "[1 2; 3 4]"  # Must preserve exact structure

        # Test 21b: More array literal edge cases
        # Mixed spaces and semicolons
        str = "[1 2; 3 4; 5 6]"  # 3×2 matrix
        @test format_text(str, SciMLStyle()) == str

        # Nested arrays
        str = "[[1, 2], [3, 4]]"
        @test format_text(str, SciMLStyle()) == str

        # Array with trailing comma (1-element array vs scalar)
        str = "[1,]"  # 1-element array
        formatted = format_text(str, SciMLStyle())
        @test formatted == "[1]" || formatted == "[1,]"  # Both are valid

        # Empty arrays with type
        str = "Float64[]"
        @test format_text(str, SciMLStyle()) == str

        str = "Vector{Int}()"
        @test format_text(str, SciMLStyle()) == str

        # Test 22: Tuple vs array distinction
        str = "(1, 2, 3)"  # Tuple
        @test format_text(str, SciMLStyle()) == str

        str = "(1,)"  # 1-element tuple (comma required)
        @test format_text(str, SciMLStyle()) == str

        # Test 23: Generator expressions
        str = "(x^2 for x in 1:10)"
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "for x in 1:10")

        # Test 24: Multi-line array construction preservation
        str = """
        A = [
            1 2 3
            4 5 6
            7 8 9
        ]
        """
        formatted = format_text(str, SciMLStyle())
        # Should preserve the matrix structure
        @test contains(formatted, "1 2 3")
        @test contains(formatted, "4 5 6")
        @test contains(formatted, "7 8 9")

        # Test 25: Coefficient with array indexing
        str = "y = 2A[i, j]"  # 2*A[i,j], not 2 A[i,j]
        @test format_text(str, SciMLStyle()) == str

        # Test 26: Multiple dispatch syntax
        str = "f(::Type{T}) where T = T"
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "where") &&
              contains(formatted, "T") &&
              contains(formatted, "Type{T}")

        # Test 27: Subtype syntax
        str = "T <: Number"
        @test format_text(str, SciMLStyle()) == str

        # Test 28: Union types
        str = "Union{Int, Float64}"
        @test format_text(str, SciMLStyle()) == str

        # Test 29: Parametric types with constraints
        str = "struct Foo{T<:Real} end"
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "T<:Real") || contains(formatted, "T <: Real")

        # Test 30: Named tuples
        str = "(a=1, b=2)"
        formatted = format_text(str, SciMLStyle())
        # Named tuples might get spaces around =
        @test formatted == str || formatted == "(a = 1, b = 2)"

        # Test 31: Keyword arguments
        str = "f(x; y=1, z=2)"
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "; y")  # Semicolon preserved

        # Test 32: Do block syntax
        str = """
        map(1:3) do x
            x^2
        end
        """
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "do x")

        # Test 33: Let block with multiple bindings
        str = "let x = 1, y = 2; x + y end"
        formatted = format_text(str, SciMLStyle())
        # Check semantic equivalence by comparing string representation without line numbers
        str_ast = replace(string(Meta.parse(str)), r"#= \S+:\d+ =#" => "")
        form_ast = replace(string(Meta.parse(formatted)), r"#= \S+:\d+ =#" => "")
        @test str_ast == form_ast

        # Test 34: Destructuring
        str = "a, b, c = 1, 2, 3"
        @test format_text(str, SciMLStyle()) == str

        # Test 35: Unicode operators
        str = "x ∈ A ∩ B"
        @test format_text(str, SciMLStyle()) == str

        # Test 36: Pipe operator
        str = "x |> f |> g"
        @test format_text(str, SciMLStyle()) == str

        # Test 37: Pairs syntax
        str = "a => b"
        @test format_text(str, SciMLStyle()) == str

        # Test 38: Quote expressions
        str = ":(x + y)"
        @test format_text(str, SciMLStyle()) == str

        # Test 39: Escaped identifiers
        str = "var\"strange name\""
        @test format_text(str, SciMLStyle()) == str

        # Test 40: Line number nodes (should be preserved in macros)
        str = """
        macro foo()
            quote
                x = 1
                y = 2
            end
        end
        """
        formatted = format_text(str, SciMLStyle())
        @test contains(formatted, "quote")
    end

    @testset "line break quality" begin
        # Helper function to analyze line utilization
        function analyze_line_quality(formatted_code)
            lines = split(formatted_code, '\n')
            non_empty_lines = filter(l -> !isempty(strip(l)), lines)

            if isempty(non_empty_lines)
                return (max_length = 0, avg_length = 0.0, num_lines = 0, efficiency = 0.0)
            end

            lengths = [length(rstrip(line)) for line in non_empty_lines]
            max_length = maximum(lengths)
            avg_length = sum(lengths) / length(lengths)

            # Efficiency: how well lines use available space (0-1)
            # Penalize both very short lines and lines over margin
            efficiency_scores = map(lengths) do len
                if len > 92
                    0.5 * (92 / len)  # Penalty for exceeding margin
                elseif len < 20
                    len / 40  # Penalty for very short lines
                else
                    len / 92  # Normal efficiency
                end
            end
            efficiency = sum(efficiency_scores) / length(efficiency_scores)

            return (
                max_length = max_length,
                avg_length = avg_length,
                num_lines = length(non_empty_lines),
                efficiency = efficiency,
            )
        end

        # Test 1: Simple expressions should stay on one line when they fit
        @testset "single line preservation" begin
            # These should remain on one line
            single_line_cases = [
                "x = a + b * c - d",
                "result = solve(prob, alg)",
                "arr[i, j] = value * scale",
                "y = sin(x) + cos(z) * exp(-t)",
                "data = [1, 2, 3, 4, 5]",
            ]

            for code in single_line_cases
                formatted = format_text(code, SciMLStyle())
                @test !contains(formatted, '\n')
                @test formatted == code
            end
        end

        # Test 2: Long lines should break efficiently
        @testset "efficient line breaking" begin
            # Function call with many parameters
            str = """
            result = solve(NonlinearProblem(f, u0, p), NewtonRaphson(; autodiff=AutoForwardDiff()), abstol=1e-10, reltol=1e-10, maxiters=1000, show_trace=true)
            """
            formatted = format_text(str, SciMLStyle())
            quality = analyze_line_quality(formatted)

            @test quality.max_length <= 92  # Should respect margin
            @test quality.avg_length > 50   # Should use space efficiently
            @test quality.efficiency > 0.6   # Good space utilization

            # Mathematical expression
            str = """
            residual = alpha * (u[i-1, j] + u[i+1, j] - 2u[i, j]) / dx^2 + beta * (u[i, j-1] + u[i, j+1] - 2u[i, j]) / dy^2 + gamma * u[i, j]
            """
            formatted = format_text(str, SciMLStyle())
            quality = analyze_line_quality(formatted)

            # Should break but maintain good line density
            @test quality.num_lines >= 2
            @test quality.avg_length > 40  # Not too many short lines
        end

        # Test 3: Type parameters should wrap nicely
        @testset "type parameter wrapping" begin
            str = """
            function f(x::AbstractArray{T,N}, y::AbstractMatrix{S}) where {T<:Real, S<:Number, N}
                return x
            end
            """
            formatted = format_text(str, SciMLStyle())
            quality = analyze_line_quality(formatted)

            # Should fit on 3 lines max
            @test quality.num_lines <= 3
            @test quality.max_length <= 92

            # Long type parameter list
            str = """
            struct MyType{T1,T2,T3,T4,T5,T6,T7,T8,T9,T10} <: AbstractType{T1,T2,T3,T4,T5,T6,T7,T8,T9,T10}
            end
            """
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, '\n')

            # Should break but not excessively
            @test length(lines) <= 4
            # No single parameter on a line
            for line in lines
                if contains(line, "T") && !contains(line, "end")
                    @test contains(line, ",") || contains(line, "{") || contains(line, "}")
                end
            end
        end

        # Test 4: Array operations should maintain structure
        @testset "array operation formatting" begin
            # Array comprehension
            str = "[f(i, j) * g(k) for i in 1:n, j in 1:m, k in 1:p if condition(i, j, k)]"
            formatted = format_text(str, SciMLStyle())

            # Should keep comprehension readable
            @test contains(formatted, "for i in 1:n, j in 1:m")
            quality = analyze_line_quality(formatted)
            @test quality.efficiency > 0.5

            # Matrix literal
            str = """
            A = [
                a11 a12 a13 a14
                a21 a22 a23 a24
                a31 a32 a33 a34
            ]
            """
            formatted = format_text(str, SciMLStyle())
            # Should preserve matrix structure
            @test contains(formatted, "a11 a12 a13 a14")
            @test contains(formatted, "a21 a22 a23 a24")
        end

        # Test 5: Function definitions with multiple arguments
        @testset "function definition formatting" begin
            # Moderate length - should stay on 2-3 lines
            str = """
            function solve(prob::ODEProblem, alg::Tsit5; abstol=1e-6, reltol=1e-3, saveat=[], callback=nothing)
                # body
            end
            """
            formatted = format_text(str, SciMLStyle())
            quality = analyze_line_quality(formatted)

            @test quality.num_lines <= 4  # Reasonable number of lines
            @test quality.avg_length > 30  # Reasonable line utilization

            # Very long parameter list
            str = """
            function complex_solver(problem::NonlinearProblem{uType,tType,isinplace}, algorithm::NewtonRaphson{CS,AD,FDT,L,P,ST,CJ}, x0::AbstractVector, p::NamedTuple; abstol::Float64=1e-8, reltol::Float64=1e-8, maxiters::Int=1000, callback=nothing, show_trace::Bool=false) where {uType,tType,isinplace,CS,AD,FDT,L,P,ST,CJ}
                # body
            end
            """
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, '\n')

            # Should break intelligently
            @test all(length(rstrip(line)) <= 92 for line in lines)
            # But not too many lines
            @test length(lines) <= 12  # Complex function may need more lines
        end

        # Test 6: Nested expressions should maintain hierarchy
        @testset "nested expression formatting" begin
            str = """
            result = transform(integrate(differentiate(interpolate(data, method=:cubic), order=2), bounds=(a, b)), scaling=:log)
            """
            formatted = format_text(str, SciMLStyle())

            # Should break at outer function calls first
            @test contains(formatted, "transform(")
            quality = analyze_line_quality(formatted)
            @test quality.efficiency > 0.5

            # Nested array access
            str = "value = data[indices[i]][subindices[j]][k]"
            formatted = format_text(str, SciMLStyle())
            # Should keep array access together when reasonable
            @test !contains(formatted, "[\n")
        end

        # Test 7: Mathematical expressions should break at operators
        @testset "mathematical expression breaking" begin
            # Long equation
            str = """
            energy = 0.5 * mass * velocity^2 + mass * gravity * height + 0.5 * spring_constant * displacement^2 + friction_coefficient * mass * gravity * distance
            """
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, '\n')

            # Should break at + operators
            for line in lines[2:end]
                stripped = strip(line)
                if !isempty(stripped)
                    # Continuation lines should start with operator or be aligned
                    @test startswith(stripped, "+") ||
                          startswith(stripped, "-") ||
                          startswith(stripped, "*") ||
                          startswith(stripped, "/") ||
                          length(lstrip(line)) < length(line)  # Or be indented
                end
            end

            quality = analyze_line_quality(formatted)
            @test quality.avg_length > 40  # Efficient use of space
        end

        # Test 8: Avoid "orphan" parameters
        @testset "avoid orphan parameters" begin
            # Should not leave single parameters on lines
            str = "f(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)"
            formatted = format_text(str, SciMLStyle())
            lines = split(formatted, '\n')

            for line in lines
                stripped = strip(line)
                # If it's just a single letter and comma/paren, it's an orphan
                if match(r"^[a-z],?\)?$", stripped) !== nothing
                    @test false  # Should not have orphan parameters
                end
            end
        end

        # Test 9: Keyword arguments should group nicely
        @testset "keyword argument grouping" begin
            str = """
            solve(prob; abstol=1e-8, reltol=1e-8, dtmin=1e-10, dtmax=0.1, maxiters=10000, adaptive=true, save_everystep=false, save_start=true, save_end=true, verbose=true)
            """
            formatted = format_text(str, SciMLStyle())

            # Should group related kwargs when possible
            lines = split(formatted, '\n')
            # First line should have multiple kwargs if they fit
            if length(lines) > 1
                @test contains(lines[1], ",") || contains(lines[1], ";")
            end

            quality = analyze_line_quality(formatted)
            @test quality.efficiency > 0.6
        end

        # Test 10: Preserve logical grouping
        @testset "logical grouping preservation" begin
            # Coordinates should stay together
            str = "plot(x1, y1, x2, y2, x3, y3; xlabel=\"Time\", ylabel=\"Value\", title=\"Results\")"
            formatted = format_text(str, SciMLStyle())

            # x,y pairs should stay together when possible
            @test contains(formatted, "x1, y1") || contains(formatted, "x1,y1")

            # Matrix multiplication chain
            str = "result = A * B * C * D * E * F"
            formatted = format_text(str, SciMLStyle())
            # Should keep some products together
            @test length(split(formatted, '\n')) <= 3
        end

        # Test 11: Real-world examples from SciML
        @testset "SciML real-world examples" begin
            # From OrdinaryDiffEq
            str = """
            @muladd function perform_step!(integrator, cache::RK4Cache, repeat_step=false)
                @unpack t, dt, uprev, u, f, p = integrator
                @unpack k1, k2, k3, k4, tmp = cache
                f(k1, uprev, p, t)
                f(k2, uprev + dt/2 * k1, p, t + dt/2)
                f(k3, uprev + dt/2 * k2, p, t + dt/2)
                f(k4, uprev + dt * k3, p, t + dt)
                @. u = uprev + dt/6 * (k1 + 2*k2 + 2*k3 + k4)
            end
            """
            formatted = format_text(str, SciMLStyle())
            quality = analyze_line_quality(formatted)

            # Should maintain readability
            @test quality.max_length <= 92
            @test quality.avg_length > 30

            # From ModelingToolkit
            str = """
            @parameters t σ ρ β
            @variables x(t) y(t) z(t)
            D = Differential(t)
            eqs = [D(x) ~ σ * (y - x), D(y) ~ x * (ρ - z) - y, D(z) ~ x * y - β * z]
            """
            formatted = format_text(str, SciMLStyle())

            # Should keep equations readable
            @test contains(formatted, "D(x) ~ σ * (y - x)")
            lines = split(formatted, '\n')
            # Equations should be nicely formatted
            eq_lines = filter(l -> contains(l, "D("), lines)
            @test length(eq_lines) > 0
        end
    end
end

end
