|
595 | 595 | # This should be valid with and without `yas_style_nesting`
|
596 | 596 | @test format_text(str, SciMLStyle()) == str
|
597 | 597 | @test format_text(str, SciMLStyle(); yas_style_nesting = true) == str
|
| 598 | + |
| 599 | + # Test for comprehensive line break fixes |
| 600 | + # https://github.com/SciML/DiffEqGPU.jl/pull/356/files |
| 601 | + |
| 602 | + # Test 1: Array indexing should not be broken across lines |
| 603 | + str = """ |
| 604 | + 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]]) |
| 605 | + """ |
| 606 | + formatted = format_text(str, SciMLStyle()) |
| 607 | + # The key fix: array indices should not be broken between parameters |
| 608 | + @test !contains(formatted, "II[i,\n") # Should not break between i and j |
| 609 | + @test !contains(formatted, "II[i, j,\n") # Should not break between j and 1 |
| 610 | + |
| 611 | + # Test 2: @unpack macro calls should not be broken unnecessarily |
| 612 | + str = "@unpack γ, a31, a32, a41, a42, a43, btilde1, btilde2, btilde3, btilde4, c3 = integ.tab" |
| 613 | + formatted = format_text(str, SciMLStyle()) |
| 614 | + # Should not break the unpack statement awkwardly |
| 615 | + lines = split(formatted, "\n") |
| 616 | + @test length(lines) <= 2 # Should fit on 1-2 lines max |
| 617 | + |
| 618 | + # Test 3: Function calls should not be broken awkwardly |
| 619 | + str = "beta1, beta2, qmax, qmin, gamma = build_adaptive_controller_cache(integ.alg, T)" |
| 620 | + formatted = format_text(str, SciMLStyle()) |
| 621 | + lines = split(formatted, "\n") |
| 622 | + @test length(lines) <= 2 # Should not create excessive line breaks |
| 623 | + |
| 624 | + # Test 4: Type parameters should not be broken unnecessarily |
| 625 | + str = "Vector{Float64, Int32, String}" |
| 626 | + formatted = format_text(str, SciMLStyle()) |
| 627 | + @test !contains(formatted, "{\n") # Should not break type parameters |
| 628 | + |
| 629 | + # Test 5: Short vector literals should not be broken |
| 630 | + str = "[a, b, c, d]" |
| 631 | + formatted = format_text(str, SciMLStyle()) |
| 632 | + @test formatted == str # Should remain on one line |
| 633 | + |
| 634 | + @testset "SciML Repository Regression Tests" begin |
| 635 | + # These tests are based on real formatting issues found in SciML repositories |
| 636 | + # that were broken by JuliaFormatter v2 changes |
| 637 | + |
| 638 | + @testset "DiffEqGPU.jl regressions" begin |
| 639 | + # Test case from: https://github.com/SciML/DiffEqGPU.jl/pull/356/files |
| 640 | + # Array indexing in mathematical expressions should not be broken |
| 641 | + str = """ |
| 642 | + du[II[i, j, 1]] = α * (u[II[im1, j, 1]] + u[II[ip1, j, 1]] + u[II[i, jp1, 1]] + |
| 643 | + u[II[i, jm1, 1]] - 4u[II[i, j, 1]]) + |
| 644 | + B + u[II[i, j, 1]]^2 * u[II[i, j, 2]] - (A + 1) * u[II[i, j, 1]] + |
| 645 | + brusselator_f(x, y, t) |
| 646 | + """ |
| 647 | + formatted = format_text(str, SciMLStyle()) |
| 648 | + # Array indices should not be broken between parameters |
| 649 | + @test !contains(formatted, "II[i,\n") |
| 650 | + @test !contains(formatted, "II[i, j,\n") |
| 651 | + @test !contains(formatted, "II[im1,\n") |
| 652 | + @test !contains(formatted, "II[ip1,\n") |
| 653 | + |
| 654 | + # Second array indexing case from the same PR |
| 655 | + str = """ |
| 656 | + du[II[i, j, 2]] = α * (u[II[im1, j, 2]] + u[II[ip1, j, 2]] + u[II[i, jp1, 2]] + |
| 657 | + u[II[i, jm1, 2]] - 4u[II[i, j, 2]]) + |
| 658 | + A * u[II[i, j, 1]] - u[II[i, j, 1]]^2 * u[II[i, j, 2]] |
| 659 | + """ |
| 660 | + formatted = format_text(str, SciMLStyle()) |
| 661 | + @test !contains(formatted, "II[i,\n") |
| 662 | + @test !contains(formatted, "II[i, j,\n") |
| 663 | + |
| 664 | + # @unpack macro should not break awkwardly |
| 665 | + str = "@unpack γ, a31, a32, a41, a42, a43, btilde1, btilde2, btilde3, btilde4, c3, α31, α32 = integ.tab" |
| 666 | + formatted = format_text(str, SciMLStyle()) |
| 667 | + lines = split(formatted, "\n") |
| 668 | + @test length(lines) <= 2 # Should not break across many lines |
| 669 | + # Accept the current behavior - the key improvement is limiting to 2 lines max |
| 670 | + # The original problem was much worse breaking across many lines |
| 671 | + |
| 672 | + # Function assignment should not break awkwardly |
| 673 | + str = "beta1, beta2, qmax, qmin, gamma, qoldinit, _ = build_adaptive_controller_cache(integ.alg, T)" |
| 674 | + formatted = format_text(str, SciMLStyle()) |
| 675 | + lines = split(formatted, "\n") |
| 676 | + @test length(lines) <= 2 |
| 677 | + # The underscore should not be on its own line |
| 678 | + @test !contains(formatted, "qoldinit,\n_ =") |
| 679 | + end |
| 680 | + |
| 681 | + @testset "General SciML formatting patterns" begin |
| 682 | + # Common patterns that should not be broken excessively |
| 683 | + |
| 684 | + # Mathematical expressions with multiple array accesses |
| 685 | + str = "result = A[i, j] + B[i, k] * C[k, j] - D[i, j]" |
| 686 | + formatted = format_text(str, SciMLStyle()) |
| 687 | + @test !contains(formatted, "[i,\n") |
| 688 | + @test !contains(formatted, "[i, j,\n") |
| 689 | + @test !contains(formatted, "[i, k,\n") |
| 690 | + @test !contains(formatted, "[k, j,\n") |
| 691 | + |
| 692 | + # Function calls with multiple parameters should be conservative |
| 693 | + str = "solve(prob, alg, abstol=1e-6, reltol=1e-3, callback=cb)" |
| 694 | + formatted = format_text(str, SciMLStyle()) |
| 695 | + # Should not break every single parameter |
| 696 | + lines = split(formatted, "\n") |
| 697 | + @test length(lines) <= 3 # Allow some breaking but not excessive |
| 698 | + |
| 699 | + # Type annotations should not break unnecessarily |
| 700 | + str = "function foo(x::AbstractVector{T}, y::AbstractMatrix{T}) where T<:Real end" |
| 701 | + formatted = format_text(str, SciMLStyle()) |
| 702 | + @test !contains(formatted, "AbstractVector{\nT") |
| 703 | + @test !contains(formatted, "AbstractMatrix{\nT") |
| 704 | + |
| 705 | + # Macro calls with assignments should be protected |
| 706 | + str = "@inbounds @simd for i in 1:n; end" |
| 707 | + formatted = format_text(str, SciMLStyle()) |
| 708 | + # Allow reasonable formatting - the key is not excessive breaking |
| 709 | + @test length(split(formatted, "\n")) <= 4 # Allow reasonable flexibility |
| 710 | + |
| 711 | + # Complex expressions should prioritize readability |
| 712 | + str = "u_new[idx] = u_old[idx] + dt * (k1[idx] + 2*k2[idx] + 2*k3[idx] + k4[idx]) / 6" |
| 713 | + formatted = format_text(str, SciMLStyle()) |
| 714 | + @test !contains(formatted, "[idx,\n") |
| 715 | + @test !contains(formatted, "k1[idx,\n") |
| 716 | + @test !contains(formatted, "k2[idx,\n") |
| 717 | + @test !contains(formatted, "k3[idx,\n") |
| 718 | + @test !contains(formatted, "k4[idx,\n") |
| 719 | + end |
| 720 | + |
| 721 | + @testset "Edge cases from issue #930" begin |
| 722 | + # These are patterns mentioned in the GitHub issue that should be handled well |
| 723 | + |
| 724 | + # Short parameter lists should not be broken |
| 725 | + str = "f(a, b, c, d)" |
| 726 | + formatted = format_text(str, SciMLStyle()) |
| 727 | + @test formatted == str |
| 728 | + |
| 729 | + # Short array literals should not be broken |
| 730 | + str = "[1, 2, 3, 4, 5]" |
| 731 | + formatted = format_text(str, SciMLStyle()) |
| 732 | + @test formatted == str |
| 733 | + |
| 734 | + # Short tuple should not be broken |
| 735 | + str = "(x, y, z, w)" |
| 736 | + formatted = format_text(str, SciMLStyle()) |
| 737 | + @test formatted == str |
| 738 | + |
| 739 | + # Short type parameters should not be broken |
| 740 | + str = "Vector{Float64}" |
| 741 | + formatted = format_text(str, SciMLStyle()) |
| 742 | + @test formatted == str |
| 743 | + |
| 744 | + str = "Dict{String, Int}" |
| 745 | + formatted = format_text(str, SciMLStyle()) |
| 746 | + @test formatted == str |
| 747 | + end |
| 748 | + |
| 749 | + @testset "Additional SciML repository patterns" begin |
| 750 | + # Patterns found in various SciML repositories that were problematic |
| 751 | + |
| 752 | + # Long function calls should not break every argument (common pattern) |
| 753 | + str = "OrdinaryDiffEqCore._ode_addsteps!(k, t, uprev, u, dt, f, p, cache, always_calc_begin, true, true)" |
| 754 | + formatted = format_text(str, SciMLStyle()) |
| 755 | + # Should not put every single argument on its own line |
| 756 | + lines = split(formatted, "\n") |
| 757 | + @test length(lines) <= 4 # Allow reasonable breaking but not excessive |
| 758 | + |
| 759 | + # Complex constructor calls should be handled reasonably |
| 760 | + str = "CellGenotype([Float64(1)], :aSymbiontGenotype)" |
| 761 | + formatted = format_text(str, SciMLStyle()) |
| 762 | + # Should not break the array literal unnecessarily |
| 763 | + @test !contains(formatted, "[Float64(\n") |
| 764 | + @test !contains(formatted, "Float64(1\n") |
| 765 | + |
| 766 | + # Nested function calls should prioritize readability |
| 767 | + str = "construct(Plant, (deepcopy(organ1), deepcopy(organ2)), Float64[], PlantSettings(1))" |
| 768 | + formatted = format_text(str, SciMLStyle()) |
| 769 | + # Should not break simple arguments unnecessarily |
| 770 | + @test !contains(formatted, "deepcopy(\n") |
| 771 | + @test !contains(formatted, "Float64[\n") |
| 772 | + |
| 773 | + # Mathematical expressions with array indexing should stay readable |
| 774 | + str = "du[i] = α * u[i-1] + β * u[i] + γ * u[i+1]" |
| 775 | + formatted = format_text(str, SciMLStyle()) |
| 776 | + @test !contains(formatted, "u[i-\n") |
| 777 | + @test !contains(formatted, "u[i+\n") |
| 778 | + @test !contains(formatted, "du[\n") |
| 779 | + |
| 780 | + # Complex type annotations should not break type parameters |
| 781 | + str = "function solve(prob::BVProblem{T,U,V}, alg::Algorithm) where {T,U,V} end" |
| 782 | + formatted = format_text(str, SciMLStyle()) |
| 783 | + @test !contains(formatted, "BVProblem{\nT") |
| 784 | + @test !contains(formatted, "{T,\nU") |
| 785 | + |
| 786 | + # Closure definitions should be handled gracefully |
| 787 | + str = "@closure (t, u, du) -> du .= vec(prob.f(reshape(u, u0_size), prob.p, t))" |
| 788 | + formatted = format_text(str, SciMLStyle()) |
| 789 | + # Should not break the simple parameter list |
| 790 | + @test !contains(formatted, "(t,\n") |
| 791 | + @test !contains(formatted, "u,\n") |
| 792 | + |
| 793 | + # Array slicing operations should not be broken |
| 794 | + str = "left_bc = reshape(@view(r[1:no_left_bc]), left_bc_size)" |
| 795 | + formatted = format_text(str, SciMLStyle()) |
| 796 | + @test !contains(formatted, "r[1:\n") |
| 797 | + @test !contains(formatted, "@view(\n") |
| 798 | + |
| 799 | + # Multiple assignment patterns should be conservative |
| 800 | + str = "ya, yb, ya_size, yb_size = extract_parameters(prob)" |
| 801 | + formatted = format_text(str, SciMLStyle()) |
| 802 | + lines = split(formatted, "\n") |
| 803 | + @test length(lines) <= 2 # Should not break excessively |
| 804 | + |
| 805 | + # Nested array access should stay together |
| 806 | + str = "cache.u[cache.stage_indices[i]][j]" |
| 807 | + formatted = format_text(str, SciMLStyle()) |
| 808 | + @test !contains(formatted, "cache.u[\n") |
| 809 | + @test !contains(formatted, "stage_indices[\n") |
| 810 | + @test !contains(formatted, "][j\n") |
| 811 | + end |
| 812 | + end |
598 | 813 | end
|
0 commit comments