Repository: fredrikekre/Runic.jl (julia)

Issue:
ERROR: failed to format input: Runic.AssertionError: is_leaf(space_node) && kind(space_node) === K"Whitespace"
This is with Julia 1.11.1 and Runic 1.0.0: I tried to format the files in [GAP.jl](http://github.com/oscar-system/GAP.jl/) and got this:
```
runic src/constructors.jl
ERROR: failed to format input: Runic.AssertionError: is_leaf(space_node) && kind(space_node) === K"Whitespace". This is unexpected, please file an issue with a reproducible example at https://github.com/fredrikekre/Runic.jl/issues/new.
Stacktrace:
 [1] indent_function_or_macro(ctx::Runic.Context, node::Runic.Node)
   @ Runic ~/.julia/packages/Runic/Ll7qO/src/runestone.jl:1752
 [2] insert_delete_mark_newlines(ctx::Runic.Context, node::Runic.Node)
   @ Runic ~/.julia/packages/Runic/Ll7qO/src/runestone.jl:3108
 [3] format_node!(ctx::Runic.Context, node::Runic.Node)
   @ Runic ~/.julia/packages/Runic/Ll7qO/src/Runic.jl:435
 [4] format_node_with_kids!(ctx::Runic.Context, node::Runic.Node)
   @ Runic ~/.julia/packages/Runic/Ll7qO/src/Runic.jl:354
 [5] format_node!(ctx::Runic.Context, node::Runic.Node)
   @ Runic ~/.julia/packages/Runic/Ll7qO/src/Runic.jl:465
```


I've narrowed it down to this code, however reading that into Julia will kill Julia:
```
function(::Type{T})(::Int) where T
end
```
So here is a less deadly version that also exhibits the issue:
```
function(::Type{T})(::Int) where T<:StepRange
end
```
Actually `creduce` also produced this, which to my surprise is valid Julia code but I don't understand why.
```
function()() end
```

Pull request description:
This patch removes an assertion about whitespace after the `function`
keyword in the indent pass. The core issue is the
`is_longform_anon_function` predicate which is wrong for the testcases,
but the assert is not needed since we can just use the next
non-whitespace noce as the signature in all cases. Fixes #109.

Patch:
diff --git a/src/runestone.jl b/src/runestone.jl
index 9f6fcf7..b1218a1 100644
--- a/src/runestone.jl
+++ b/src/runestone.jl
@@ -1599,19 +1599,9 @@ function indent_function_or_macro(ctx::Context, node::Node)
         kids[func_idx] = add_tag(func_node, TAG_INDENT)
         any_kid_changed = true
     end
-    # Second node is the space between keyword and name
-    if !(is_longform_anon_function(node) || is_longform_functor(node))
-        space_idx = 2
-        space_node = kids[space_idx]
-        @assert is_leaf(space_node) && kind(space_node) === K"Whitespace"
-    end
-    # Third node is the signature (call/where/::) for standard method definitions but just
-    # an Identifier for cases like `function f end`.
+    # The signature is the next non-whitespace node. It is a (call/where/::) for standard
+    # method definitions but just an Identifier for cases like `function f end`.
     sig_idx = findnext(x -> !JuliaSyntax.is_whitespace(x), kids, func_idx + 1)::Int
-    if sig_idx == 2
-        # Only case where no space is needed after the keyword
-        @assert is_longform_anon_function(node) || is_longform_functor(node)
-    end
     sig_node = kids[sig_idx]
     # Identifier for regular names but "not function call" for empty functions with Unicode
     # symbols??


Test patch:
diff --git a/test/runtests.jl b/test/runtests.jl
index fc12f82..728c61d 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -827,6 +827,10 @@ end
         # TODO: Spaces after function keyword isn't removed.
         @test format_string("function$(sp)(a * b)\nreturn\nend") ==
             "function$(sp)(a * b)\n    return\nend"
+        # https://github.com/fredrikekre/Runic.jl/issues/109
+        @test format_string("function$(sp)(::Type{T})(::Int) where {T}\n$(sp)return T\n$(sp)end") ==
+            "function (::Type{T})(::Int) where {T}\n    return T\nend"
+        @test format_string("function$(sp)()() end") == "function ()() end"
         # Multiline strings inside lists
         for trip in ("\"\"\"", "```")
             @test format_string("println(io, $(trip)\n$(sp)a\n$(sp)\n$(sp)b\n$(sp)$(trip))") ==