Repository: domluna/JuliaFormatter.jl
Pull request #586 (2022-05-22 18:55:31)

Add option to separate keyword arguments with a semicolon
> default: `false`

When set to `true`, keyword arguments in a function call will be separated with a semicolon.

```julia
f(a, b=1)

->

f(a; b=1)
```

blue and yas style have this set to `true` by default


Patch:
diff --git a/Project.toml b/Project.toml
index 26792381..9804fbe3 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.22.11"
+version = "0.23.0"
 
 [deps]
 CSTParser = "00ebfdb7-1f24-5e51-bd34-a7502290713f"
diff --git a/README.md b/README.md
index 0ba2fa0b..4df1c6fb 100644
--- a/README.md
+++ b/README.md
@@ -404,6 +404,20 @@ d = 4
 end
 ```
 
+### `separate_kwargs_with_semicolon`
+
+> default: `false`
+
+When set to `true`, keyword arguments in a function call will be separated with a semicolon.
+
+```julia
+f(a, b=1)
+
+->
+
+f(a; b=1)
+```
+
 ### File Options
 
 ### `overwrite`
diff --git a/src/JuliaFormatter.jl b/src/JuliaFormatter.jl
index 6e88f730..5958b928 100644
--- a/src/JuliaFormatter.jl
+++ b/src/JuliaFormatter.jl
@@ -519,6 +519,21 @@ d = 4
 
 end
 ```
+
+### `separate_kwargs_with_semicolon`
+
+> default: `false`
+
+When set to `true`, keyword arguments in a function call will be separated with a semicolon.
+
+```julia
+f(a, b=1)
+
+->
+
+f(a; b=1)
+```
+
 """
 function format_text(text::AbstractString; style::AbstractStyle = DefaultStyle(), kwargs...)
     return format_text(text, style; kwargs...)
diff --git a/src/options.jl b/src/options.jl
index 48a6bdef..4ded0464 100644
--- a/src/options.jl
+++ b/src/options.jl
@@ -22,6 +22,7 @@ Base.@kwdef struct Options
     join_lines_based_on_source::Bool = false
     trailing_comma::Union{Bool,Nothing} = true
     indent_submodule::Bool = false
+    separate_kwargs_with_semicolon::Bool = false
 end
 
 function needs_alignment(opts::Options)
diff --git a/src/styles/blue/pretty.jl b/src/styles/blue/pretty.jl
index f8981f9f..7c4ef506 100644
--- a/src/styles/blue/pretty.jl
+++ b/src/styles/blue/pretty.jl
@@ -18,6 +18,7 @@ Configurable options with different defaults to [`DefaultStyle`](@ref) are:
 - `pipe_to_function_call` = true
 - `whitespace_in_kwargs` = false
 - `annotate_untyped_fields_with_any` = false
+- `separate_kwargs_with_semicolon` = true
 """
 struct BlueStyle <: AbstractStyle
     innerstyle::Union{Nothing,AbstractStyle}
@@ -39,6 +40,7 @@ function options(style::BlueStyle)
         annotate_untyped_fields_with_any = false,
         conditional_to_if = true,
         indent_submodule = true,
+        separate_kwargs_with_semicolon = true,
     )
 end
 
@@ -47,15 +49,6 @@ function is_binaryop_nestable(::BlueStyle, cst::CSTParser.EXPR)
     return is_binaryop_nestable(DefaultStyle(), cst)
 end
 
-function p_call(bs::BlueStyle, cst::CSTParser.EXPR, s::State)
-    style = getstyle(bs)
-    t = p_call(DefaultStyle(style), cst, s)
-    if !parent_is(cst, n -> is_function_or_macro_def(n) || n.head == :macrocall)
-        separate_kwargs_with_semicolon!(t)
-    end
-    t
-end
-
 function p_do(bs::BlueStyle, cst::CSTParser.EXPR, s::State)
     style = getstyle(bs)
     t = FST(Do, cst, nspaces(s))
diff --git a/src/styles/default/pretty.jl b/src/styles/default/pretty.jl
index 1f0304f2..bd73725d 100644
--- a/src/styles/default/pretty.jl
+++ b/src/styles/default/pretty.jl
@@ -1775,6 +1775,12 @@ function p_call(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
             add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
+
+    if s.opts.separate_kwargs_with_semicolon &&
+       (!parent_is(cst, n -> is_function_or_macro_def(n) || n.head == :macrocall))
+        separate_kwargs_with_semicolon!(t)
+    end
+
     t
 end
 p_call(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
diff --git a/src/styles/yas/pretty.jl b/src/styles/yas/pretty.jl
index 08d978d3..2fe5fad1 100644
--- a/src/styles/yas/pretty.jl
+++ b/src/styles/yas/pretty.jl
@@ -14,6 +14,7 @@ Configurable options with different defaults to [`DefaultStyle`](@ref) are:
 - `always_use_return` = true
 - `whitespace_in_kwargs` = false
 - `join_lines_based_on_source` = true
+- `separate_kwargs_with_semicolon` = true
 """
 struct YASStyle <: AbstractStyle
     innerstyle::Union{Nothing,AbstractStyle}
@@ -32,6 +33,7 @@ function options(style::YASStyle)
         always_use_return = true,
         whitespace_in_kwargs = false,
         join_lines_based_on_source = true,
+        separate_kwargs_with_semicolon = true,
     )
 end
 
@@ -256,9 +258,12 @@ function p_call(ys::YASStyle, cst::CSTParser.EXPR, s::State)
             add_node!(t, n, s, join_lines = true)
         end
     end
-    if !parent_is(cst, is_function_or_macro_def)
+
+    if s.opts.separate_kwargs_with_semicolon &&
+       (!parent_is(cst, n -> is_function_or_macro_def(n) || n.head == :macrocall))
         separate_kwargs_with_semicolon!(t)
     end
+
     t
 end
 function p_vect(ys::YASStyle, cst::CSTParser.EXPR, s::State)
@@ -300,6 +305,7 @@ function p_vcat(ys::YASStyle, cst::CSTParser.EXPR, s::State)
                 n_semicolons += 1
                 semicolons = s.doc.semicolons[n.startline]
                 count = popfirst!(semicolons)
+                # @info "" count n_semicolons
                 if i != length(cst) - 1
                     if count > 1
                         for _ = 1:count


Test patch:
diff --git a/test/issues.jl b/test/issues.jl
index 68b0034c..8a76c07d 100644
--- a/test/issues.jl
+++ b/test/issues.jl
@@ -984,14 +984,52 @@
             AWSS3.s3_sign_url(config, path.bucket, path.key, Dates.value(Second(duration))),
         )
         """
-        @test bluefmt(str, 4, 100, whitespace_in_kwargs = false) == str
+        @test fmt(
+            str,
+            4,
+            100,
+            whitespace_in_kwargs = false,
+            separate_kwargs_with_semicolon = true,
+        ) == str
         str = """
         @deprecate(
             presign(path::AWSS3.S3Path; duration::Period=Hour(1), config::AWSConfig=aws_config()),
             AWSS3.s3_sign_url(config, path.bucket, path.key, Dates.value(Second(duration))),
         )
         """
-        @test bluefmt(str, 4, 100, whitespace_in_kwargs = false) == str
+        @test fmt(
+            str,
+            4,
+            100,
+            whitespace_in_kwargs = false,
+            separate_kwargs_with_semicolon = true,
+        ) == str
+
+        str = """
+        @deprecate(presign(path::AWSS3.S3Path, duration::Period=Hour(1); config::AWSConfig=aws_config()),
+                   AWSS3.s3_sign_url(config, path.bucket, path.key, Dates.value(Second(duration))),)
+        """
+        @test yasfmt(
+            str,
+            4,
+            100,
+            margin = 100,
+            whitespace_in_kwargs = false,
+            separate_kwargs_with_semicolon = true,
+        ) == str
+
+        str = """
+        @deprecate(presign(path::AWSS3.S3Path, duration::Period=Hour(1), config::AWSConfig=aws_config()),
+                   AWSS3.s3_sign_url(config, path.bucket, path.key, Dates.value(Second(duration))),)
+        """
+        @test yasfmt(
+            str,
+            4,
+            100,
+            margin = 100,
+            whitespace_in_kwargs = false,
+            separate_kwargs_with_semicolon = true,
+        ) == str
     end
 
     @testset "485" begin
diff --git a/test/options.jl b/test/options.jl
index 4bd87b19..0a78369b 100644
--- a/test/options.jl
+++ b/test/options.jl
@@ -2000,4 +2000,22 @@
         """
         @test fmt(str_, 2, 21, indent_submodule = true) == str
     end
+
+    @testset "`separate_kwargs_with_semicolon`" begin
+        str_ = """
+        f(a, b = 10)
+        """
+        str = """
+        f(a; b = 10)
+        """
+        @test fmt(str_, separate_kwargs_with_semicolon = true) == str
+
+        str_ = """
+        f(a, b = 10)
+        """
+        str = """
+        f(a; b = 10)
+        """
+        @test yasfmt(str_, separate_kwargs_with_semicolon = true) == str
+    end
 end