Repository: domluna/JuliaFormatter.jl (julia)

Issue:
3 space alignment after ifs should not be done for BlueStyle
Consider the following code.
It is valid-ish according to BlueStyle.
Valid-ish becuase BlueStyle doesn't make any statement about breaking lines after boolean operators to stay within line limits
So it should be left alone.
```julia
    if primal_name isa Symbol ||
        Meta.isexpr(primal_name, :(.)) ||
        Meta.isexpr(primal_name, :curly)
        
        foo()
    end
```

The output of  JuliaFormatter on the other hand is not right.
    
```julia
julia> format_text(str, BlueStyle()) |> println
if primal_name isa Symbol ||
   Meta.isexpr(primal_name, :(.)) ||
   Meta.isexpr(primal_name, :curly)
    foo()
end
```

It has changed to use 3 spaces to align with the `if`.
BlueStyle *never* does visual alignment, only indenting with 4 spaces.

Pull request description:
fix #485 

Extends nesting of Binary, Chain, and Comparison nodes so that you can provide a custom indent rather than relying on the line offset. The former is preferred by BlueStyle.

Patch:
diff --git a/Project.toml b/Project.toml
index c04519c31..deae5daf3 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "JuliaFormatter"
 uuid = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
 authors = ["Dominique Luna <dluna132@gmail.com>"]
-version = "0.17.1"
+version = "0.17.2"
 
 [deps]
 CSTParser = "00ebfdb7-1f24-5e51-bd34-a7502290713f"
diff --git a/src/styles/blue/nest.jl b/src/styles/blue/nest.jl
index 050218899..9fe61e2c7 100644
--- a/src/styles/blue/nest.jl
+++ b/src/styles/blue/nest.jl
@@ -149,5 +149,22 @@ end
 
 function n_binaryopcall!(bs::BlueStyle, fst::FST, s::State)
     style = getstyle(bs)
-    n_binaryopcall!(YASStyle(style), fst, s)
+    if fst.ref !== nothing && parent_is(fst.ref[], n -> is_if(n) || n.head === :macrocall)
+        n_binaryopcall!(YASStyle(style), fst, s; indent = fst.indent + s.opts.indent)
+    else
+        n_binaryopcall!(YASStyle(style), fst, s)
+    end
+    return
+end
+
+function n_chainopcall!(bs::BlueStyle, fst::FST, s::State)
+    style = getstyle(bs)
+    if fst.ref !== nothing && parent_is(fst.ref[], n -> is_if(n) || n.head === :macrocall)
+        n_block!(DefaultStyle(style), fst, s; indent = fst.indent + s.opts.indent)
+    else
+        n_block!(DefaultStyle(style), fst, s; indent = s.line_offset)
+    end
+    return
 end
+
+n_comparison!(bs::BlueStyle, fst::FST, s::State) = n_chainopcall!(bs, fst, s)
diff --git a/src/styles/default/nest.jl b/src/styles/default/nest.jl
index 178bbb3d1..0b2fd2d5b 100644
--- a/src/styles/default/nest.jl
+++ b/src/styles/default/nest.jl
@@ -640,7 +640,7 @@ function no_unnest(fst::FST)
     return false
 end
 
-function n_binaryopcall!(ds::DefaultStyle, fst::FST, s::State)
+function n_binaryopcall!(ds::DefaultStyle, fst::FST, s::State; indent::Int = -1)
     style = getstyle(ds)
     line_offset = s.line_offset
     line_margin = line_offset + length(fst) + fst.extra_margin
@@ -679,7 +679,11 @@ function n_binaryopcall!(ds::DefaultStyle, fst::FST, s::State)
             end
             add_indent!(fst[end], s, s.opts.indent)
         else
-            fst.indent = s.line_offset
+            if indent >= 0
+                fst.indent = indent
+            else
+                fst.indent = s.line_offset
+            end
         end
 
         # rhs
@@ -756,8 +760,8 @@ function n_binaryopcall!(ds::DefaultStyle, fst::FST, s::State)
         end
     end
 end
-n_binaryopcall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
-    n_binaryopcall!(DefaultStyle(style), fst, s)
+n_binaryopcall!(style::S, fst::FST, s::State; indent = -1) where {S<:AbstractStyle} =
+    n_binaryopcall!(DefaultStyle(style), fst, s; indent = indent)
 
 function n_for!(ds::DefaultStyle, fst::FST, s::State)
     style = getstyle(ds)
diff --git a/src/styles/yas/nest.jl b/src/styles/yas/nest.jl
index abf2f9355..e23166c74 100644
--- a/src/styles/yas/nest.jl
+++ b/src/styles/yas/nest.jl
@@ -162,10 +162,10 @@ function n_comparison!(ys::YASStyle, fst::FST, s::State)
     n_block!(DefaultStyle(style), fst, s, indent = s.line_offset)
 end
 
-function n_binaryopcall!(ys::YASStyle, fst::FST, s::State)
+function n_binaryopcall!(ys::YASStyle, fst::FST, s::State; indent::Int = -1)
     style = getstyle(ys)
     if findfirst(n -> n.typ === PLACEHOLDER, fst.nodes) !== nothing
-        n_binaryopcall!(DefaultStyle(style), fst, s)
+        n_binaryopcall!(DefaultStyle(style), fst, s; indent = indent)
         return
     end
 


Test patch:
diff --git a/test/files/ChainRules.jl/test/rulesets/Base/array.jl b/test/files/ChainRules.jl/test/rulesets/Base/array.jl
index a93509179..60efe2850 100644
--- a/test/files/ChainRules.jl/test/rulesets/Base/array.jl
+++ b/test/files/ChainRules.jl/test/rulesets/Base/array.jl
@@ -96,7 +96,7 @@ end
     # test_rrule(reduce, hcat, adjs ⊢ map(m -> rand(size(m)), adjs))
     dy = 1 ./ reduce(hcat, adjs)
     @test rrule(reduce, hcat, adjs)[2](dy)[3] ≈
-          rrule(reduce, hcat, collect.(adjs))[2](dy)[3]
+        rrule(reduce, hcat, collect.(adjs))[2](dy)[3]
 
     # mix types
     mats = [randn(2, 2), rand(2, 2)']
diff --git a/test/files/ChainRules.jl/test/rulesets/Base/mapreduce.jl b/test/files/ChainRules.jl/test/rulesets/Base/mapreduce.jl
index ff408534f..7bf23f95d 100644
--- a/test/files/ChainRules.jl/test/rulesets/Base/mapreduce.jl
+++ b/test/files/ChainRules.jl/test/rulesets/Base/mapreduce.jl
@@ -169,12 +169,12 @@ struct SumRuleConfig <: RuleConfig{Union{HasReverseMode}} end
                     unthunk(rrule(prod, UpperTriangular(rand(T, 3, 3)))[2](1.0)[2])
                 )
                 @test unthunk(rrule(prod, UpperTriangular(ones(T, 2, 2)))[2](1.0)[2]) ==
-                      UpperTriangular([0.0 0; 1 0])
+                    UpperTriangular([0.0 0; 1 0])
 
                 # Symmetric -- at least this doesn't have zeros, still an unlikely combination
                 xs = Symmetric(rand(T, 4, 4))
                 @test unthunk(rrule(prod, Symmetric(T[1 2; -333 4]))[2](1.0)[2]) ==
-                      [16 8; 8 4]
+                    [16 8; 8 4]
                 # TODO debug why these fail  https://github.com/JuliaDiff/ChainRules.jl/issues/475
                 @test_skip test_rrule(prod, xs)
                 @test_skip test_rrule(prod, xs; fkwargs=(dims=2,))
diff --git a/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/factorization.jl b/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/factorization.jl
index cfadc2918..13808ddd4 100644
--- a/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/factorization.jl
+++ b/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/factorization.jl
@@ -190,7 +190,7 @@ end
                 @test Ḟ_ad.values ≈ Ḟ_fd.values
                 @test Ḟ_ad.vectors ≈ Ḟ_fd.vectors
                 @test frule((ZeroTangent(), ZeroTangent()), eigen!, copy(X)) ==
-                      (F, ZeroTangent())
+                    (F, ZeroTangent())
 
                 @testset "tangents are real when outputs are" begin
                     # hermitian matrices have real eigenvalues and, when real, real eigenvectors
@@ -219,7 +219,7 @@ end
                 # return arrays of either real or complex values based solely on the input values (not the
                 # input types). See https://github.com/JuliaLang/julia/issues/41243
                 @test X̄_vectors_ad ≈
-                      j′vp(_fdm, x -> complex.(eigen(x).vectors), complex.(V̄), X)[1] rtol =
+                    j′vp(_fdm, x -> complex.(eigen(x).vectors), complex.(V̄), X)[1] rtol =
                     1e-6
                 F̄ = CT(; values=λ̄, vectors=V̄)
                 s̄elf, X̄_ad = @maybe_inferred back(F̄)
@@ -286,7 +286,7 @@ end
 
                     F = eigen!(copy(A))
                     @test frule((ZeroTangent(), ZeroTangent()), eigen!, copy(A)) ==
-                          (F, ZeroTangent())
+                        (F, ZeroTangent())
                     F_ad, ∂F_ad = frule((ZeroTangent(), copy(ΔA)), eigen!, copy(A))
                     @test F_ad == F
                     @test ∂F_ad isa Tangent{typeof(F)}
@@ -342,7 +342,7 @@ end
                 X = randn(T, n, n)
                 test_frule(eigvals!, X)
                 @test frule((ZeroTangent(), ZeroTangent()), eigvals!, copy(X))[2] ==
-                      ZeroTangent()
+                    ZeroTangent()
 
                 @testset "tangents are real when outputs are" begin
                     # hermitian matrices have real eigenvalues
@@ -389,7 +389,7 @@ end
                     @test ∂A isa typeof(A)
                     @test ∂A ≈ j′vp(_fdm, A -> eigvals(Matrix(Hermitian(A))), Δλ, A)[1]
                     @test @maybe_inferred(back(ZeroTangent())) ==
-                          (NoTangent(), ZeroTangent())
+                        (NoTangent(), ZeroTangent())
                 end
             end
         end
diff --git a/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/norm.jl b/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/norm.jl
index 6cef781ea..cccf5abe1 100644
--- a/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/norm.jl
+++ b/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/norm.jl
@@ -198,6 +198,6 @@ end
         x = randn(T, 3)
         test_rrule(normalize, x, p)
         @test rrule(normalize, x, p)[2](ZeroTangent()) ===
-              (NoTangent(), ZeroTangent(), ZeroTangent())
+            (NoTangent(), ZeroTangent(), ZeroTangent())
     end
 end
diff --git a/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/symmetric.jl b/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/symmetric.jl
index 0a770317f..2be9f3c3b 100644
--- a/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/symmetric.jl
+++ b/test/files/ChainRules.jl/test/rulesets/LinearAlgebra/symmetric.jl
@@ -419,14 +419,14 @@
                     ΔA = TA(randn(T, n, n))
                     _, ∂Y = frule((ZeroTangent(), ΔA), f, A)
                     @test parent(∂Y) ≈
-                          jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A.data, ΔA.data))
+                        jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A.data, ΔA.data))
 
                     λ[1:m] .= λ[(m + 1):(2m)]
                     A2 = TA(U * Diagonal(λ) * U')
                     ΔA2 = TA(randn(T, n, n))
                     _, ∂Y2 = frule((ZeroTangent(), ΔA2), f, A2)
                     @test parent(∂Y2) ≈
-                          jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A2.data, ΔA2.data))
+                        jvp(_fdm, x -> Matrix{TC}(parent(f(TA(x)))), (A2.data, ΔA2.data))
                 end
 
                 f ∉ (log, sqrt, acosh) && @testset "low-rank matrix" begin
diff --git a/test/issues.jl b/test/issues.jl
index a61bdc0fc..bcb120166 100644
--- a/test/issues.jl
+++ b/test/issues.jl
@@ -953,4 +953,60 @@
         """
         @test bluefmt(str_, 4, 100, whitespace_in_kwargs = false) == str
     end
+
+    @testset "485" begin
+        str = """
+        if primal_name isa Symbol ||
+            Meta.isexpr(primal_name, :(.)) ||
+            Meta.isexpr(primal_name, :curly)
+            foo()
+        end
+        """
+        @test bluefmt(str, 4, 80) == str
+
+        str_ = """
+        if a && b
+        end
+        """
+        str = """
+        if a &&
+            b
+        end
+        """
+        @test bluefmt(str_, 4, 1) == str
+
+        str_ = """
+        @test foo == bar == baz
+        """
+        str = """
+        @test foo ==
+            bar ==
+            baz
+        """
+        @test bluefmt(str_, 4, 1) == str
+
+        str_ = """
+        @test foo == bar
+        """
+        str = """
+        @test foo ==
+            bar
+        """
+        @test bluefmt(str_, 4, 1) == str
+
+        str = """
+        const a =
+            arg1 +
+            arg2 +
+            arg3
+        """
+        @test bluefmt(str, 4, 1) == str
+
+        str = """
+        const a =
+            arg1 +
+            arg2
+        """
+        @test bluefmt(str, 4, 1) == str
+    end
 end