Repository: domluna/JuliaFormatter.jl
Pull request #432 (2021-06-20 02:42:30)

Handle non std identifier (CSTParser terminalogy)
An example of this is `var"##iv#469"` which CSTParser parses as a identifier and string component

- var
- "##iv#469"

but `CSTParser.isidentifier` also returns `true` which the formatter
expects the value to come from the `val` field of the CST Expr.

helps with #427 

ref https://github.com/domluna/JuliaFormatter.jl/issues/427#issuecomment-864463433


Patch:
diff --git a/Project.toml b/Project.toml
index 8e2128d2..95c2325f 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.14.7"
+version = "0.14.8"
 
 [deps]
 CSTParser = "00ebfdb7-1f24-5e51-bd34-a7502290713f"
diff --git a/src/fst.jl b/src/fst.jl
index 9ae27111..79e3ccc0 100644
--- a/src/fst.jl
+++ b/src/fst.jl
@@ -16,6 +16,7 @@
     OPERATOR,
     PUNCTUATION,
     IDENTIFIER,
+    # non-leaf nodes
     MacroBlock,
     MacroCall,
     MacroStr,
@@ -78,6 +79,7 @@
     Quotenode,
     Unknown,
     As,
+    NonStdIdentifier, # i.e. var"##iv369"
 )
 
 @enum(NestBehavior, AllowNest, AlwaysNest, NeverNest, NeverNestNode)
diff --git a/src/styles/default/pretty.jl b/src/styles/default/pretty.jl
index efe9a628..bb6ee83b 100644
--- a/src/styles/default/pretty.jl
+++ b/src/styles/default/pretty.jl
@@ -1,7 +1,9 @@
 # Creates a _prettified_ version of a CST.
 function pretty(ds::DefaultStyle, cst::CSTParser.EXPR, s::State; kwargs...)
     style = getstyle(ds)
-    if CSTParser.isidentifier(cst)
+    if cst.head === :NONSTDIDENTIFIER
+        return p_nonstdidentifier(style, cst, s)
+    elseif CSTParser.isidentifier(cst)
         return p_identifier(style, cst, s)
     elseif CSTParser.isoperator(cst)
         return p_operator(style, cst, s)
@@ -139,7 +141,6 @@ function pretty(ds::DefaultStyle, cst::CSTParser.EXPR, s::State; kwargs...)
         return p_quotenode(style, cst, s)
     end
 
-    # @warn "unknown type" cst
     t = FST(Unknown, cst, nspaces(s))
     for a in cst
         if CSTParser.is_nothing(a)
@@ -168,6 +169,17 @@ end
 p_file(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
     p_file(DefaultStyle(style), cst, s)
 
+@inline function p_nonstdidentifier(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
+    t = FST(NonStdIdentifier, cst, nspaces(s))
+    for a in cst.args
+        add_node!(t, pretty(style, a, s), s, join_lines = true)
+    end
+    t
+end
+p_nonstdidentifier(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_nonstdidentifier(DefaultStyle(style), cst, s)
+
 @inline function p_identifier(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
     loc = cursor_loc(s)
     s.offset += length(cst.val) + (cst.fullspan - cst.span)


Test patch:
diff --git a/test/issues.jl b/test/issues.jl
index 4395f28f..a9817b83 100644
--- a/test/issues.jl
+++ b/test/issues.jl
@@ -680,15 +680,15 @@
         new{T1,
             T2}(arg1,
                 arg2)"""
-        @test yasfmt(str_, 4, 1) == str
+        @test yasfmt(str_, m = 1) == str
     end
 
     if VERSION >= v"1.6.0"
         @testset "issue 396 (import as)" begin
             str = """import Base.threads as th"""
             @test fmt(str) == str
-            @test fmt(str, margin = 1) == str
-            @test fmt(str, margin = 1, import_to_using = true) == str
+            @test fmt(str, m = 1) == str
+            @test fmt(str, m = 1, import_to_using = true) == str
         end
     end
 
@@ -743,13 +743,13 @@
         [z for y in x for z in y]
         """
         @test yasfmt(str) == str
-        @test yasfmt(str, margin = 25) == str
+        @test yasfmt(str, m = 25) == str
 
         str_ = """
-        [z
-         for y in x for z in y]
+        [z for y in x
+         for z in y]
         """
-        @test yasfmt(str_, margin = 24) == str
+        @test yasfmt(str, m = 24) == str_
 
         str_ = """
         [z
@@ -758,6 +758,16 @@
          for z in
              y]
         """
-        @test yasfmt(str_, margin = 1) == str
+        @test yasfmt(str, m = 1) == str_
+    end
+
+    @testset "issue 427" begin
+        str = "var\"##iv#469\" = (@variables(t))[1]"
+        @test fmt(str) == str
+
+        str_ = """
+        var\"##iv#469\" =
+            (@variables(t))[1]"""
+        @test fmt(str, m = length(str) - 1) == str_
     end
 end
diff --git a/test/runtests.jl b/test/runtests.jl
index 0714870a..3815dca2 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -7,6 +7,16 @@ fmt1(s; i = 4, m = 80, kwargs...) =
     JuliaFormatter.format_text(s; kwargs..., indent = i, margin = m)
 fmt1(s, i, m; kwargs...) = fmt1(s; kwargs..., i = i, m = m)
 
+yasfmt1(str) = fmt1(str; style = YASStyle(), options(DefaultStyle())...)
+yasfmt(str; i = 4, m = 80, kwargs...) =
+    fmt(str; i = i, m = m, style = YASStyle(), kwargs...)
+yasfmt(str, i::Int, m::Int; kwargs...) = yasfmt(str; i = i, m = m, kwargs...)
+
+bluefmt1(str) = fmt1(str; style = BlueStyle(), options(DefaultStyle())...)
+bluefmt(str; i = 4, m = 80, kwargs...) =
+    fmt(str; i = i, m = m, style = BlueStyle(), kwargs...)
+bluefmt(str, i::Int, m::Int; kwargs...) = bluefmt(str; i = i, m = m, kwargs...)
+
 # Verifies formatting the formatted text
 # results in the same output
 function fmt(s; i = 4, m = 80, kwargs...)
@@ -35,12 +45,6 @@ function run_nest(text::String; opts = Options(), style = DefaultStyle())
 end
 run_nest(text::String, margin::Int) = run_nest(text, opts = Options(margin = margin))
 
-yasfmt1(str) = fmt1(str; style = YASStyle(), options(DefaultStyle())...)
-yasfmt(str, i = 4, m = 80; kwargs...) = fmt(str, i, m; style = YASStyle(), kwargs...)
-
-bluefmt1(str) = fmt1(str; style = BlueStyle(), options(DefaultStyle())...)
-bluefmt(str, i = 4, m = 80; kwargs...) = fmt(str, i, m; style = BlueStyle(), kwargs...)
-
 @testset "JuliaFormatter" begin
     include("default_style.jl")
     include("yas_style.jl")