@@ -3463,186 +3463,3 @@ function spaces_around_comments(ctx::Context, node::Node)
34633463 return make_node (node, kids′)
34643464 end
34653465end
3466-
3467- function return_node (ctx:: Context , ret:: Node )
3468- ws = Node (JuliaSyntax. SyntaxHead (K " Whitespace" , JuliaSyntax. TRIVIA_FLAG), 1 )
3469- kids = [
3470- Node (JuliaSyntax. SyntaxHead (K " return" , 0 ), 6 ),
3471- ]
3472- if is_leaf (ret)
3473- replace_bytes! (ctx, " return " , 0 )
3474- push! (kids, ws)
3475- push! (kids, ret)
3476- else
3477- @assert ! (kind (first_leaf (ret)) in KSet " NewlineWs Whitespace" )
3478- replace_bytes! (ctx, " return " , 0 )
3479- push! (kids, ws)
3480- push! (kids, ret)
3481- end
3482- return Node (JuliaSyntax. SyntaxHead (K " return" , 0 ), kids)
3483- end
3484-
3485- function has_return (node:: Node )
3486- kids = verified_kids (node)
3487- if kind (node) in KSet " let catch else finally"
3488- idx = findfirst (x -> kind (x) === K " block" , kids):: Int
3489- if kind (node) === K " let"
3490- idx = findnext (x -> kind (x) === K " block" , kids, idx + 1 ):: Int
3491- end
3492- return has_return (kids[idx])
3493- elseif kind (node) in KSet " try if elseif"
3494- # Look for the initial try/if block and then for
3495- # catch/else/finally (for try) or elseif/else (for if).
3496- pred = function (x)
3497- return ! is_leaf (x) && kind (x) in KSet " catch else finally elseif block"
3498- end
3499- idx = findfirst (pred, kids)
3500- while idx != = nothing
3501- has_return (kids[idx]) && return true
3502- idx = findnext (pred, kids, idx + 1 )
3503- end
3504- return false
3505- elseif kind (node) === K " macrocall"
3506- # Check direct kids but also recurse into blocks to catch e.g. `@foo begin ... end`.
3507- idx = findfirst (x -> kind (x) === K " return" , kids)
3508- idx === nothing || return true
3509- return any (kids) do x
3510- return ! is_leaf (x) && kind (x) in KSet " let try if block macrocall" && has_return (x)
3511- end
3512- elseif kind (node) === K " block"
3513- # Don't care whether this is the last expression,
3514- # that is the job of a linter or something I guess.
3515- return findfirst (x -> kind (x) === K " return" , kids) != = nothing
3516- else
3517- unreachable ()
3518- end
3519- end
3520-
3521- function explicit_return_block (ctx, node)
3522- @assert kind (node) === K " block"
3523- if has_return (node)
3524- # If the block already has a return node (anywhere) we accept it and move on.
3525- return nothing
3526- end
3527- kids = verified_kids (node)
3528- kids′ = kids
3529- rexpr_idx = findlast (! JuliaSyntax. is_whitespace, kids′)
3530- if rexpr_idx === nothing
3531- # Empty block. TODO : Perhaps add `return nothing`?
3532- return nothing
3533- end
3534- rexpr = kids′[rexpr_idx]
3535- @assert kind (rexpr) != = K " return" # Should have been caught by has_return
3536- if is_leaf (rexpr) ||
3537- kind (rexpr) in KSet " call dotcall tuple vect ref hcat typed_hcat vcat typed_vcat \
3538- ? && || :: juxtapose <: >: comparison string . -> comprehension do macro \
3539- typed_comprehension where parens curly function quote global local =" ||
3540- is_string_macro (rexpr) || is_assignment (rexpr) ||
3541- (kind (rexpr) in KSet " let if try" && ! has_return (rexpr)) ||
3542- (kind (rexpr) === K " macrocall" && ! has_return (rexpr)) ||
3543- (is_begin_block (rexpr) && ! has_return (rexpr)) ||
3544- kind (rexpr) === K " quote" && JuliaSyntax. has_flags (rexpr, JuliaSyntax. COLON_QUOTE)
3545- # The cases caught in this branch are simple, just wrap the last expression in a
3546- # return node. Also make sure the previous node is a K"NewlineWs".
3547- for i in 1 : (rexpr_idx - 1 )
3548- accept_node! (ctx, kids′[i])
3549- end
3550- # If this is a call node, and the call the function name contains `throw` or `error` we
3551- # bail because `return throw(...)` looks kinda stupid.
3552- if kind (rexpr) === K " call"
3553- call_kids = verified_kids (rexpr)
3554- fname_idx = findfirst (! JuliaSyntax. is_whitespace, call_kids):: Int
3555- @assert fname_idx == firstindex (call_kids)
3556- local fname
3557- let p = position (ctx. fmt_io)
3558- fname = String (read_bytes (ctx, call_kids[fname_idx]))
3559- seek (ctx. fmt_io, p)
3560- end
3561- if contains (fname, " throw" ) || contains (fname, " error" )
3562- return nothing
3563- end
3564- end
3565- # We will make changes so copy
3566- kids′ = kids′ === kids ? copy (kids) : kids′
3567- # Make sure the previous node is a K"NewlineWs"
3568- if ! kmatch (kids′, KSet " NewlineWs" , rexpr_idx - 1 )
3569- spn = 0
3570- @assert kind (first_leaf (rexpr)) != = K " NewlineWs"
3571- # Can it happen that there are whitespace hidden in the previous node?
3572- # Let's see if this assert ever fire.
3573- if rexpr_idx > 1
3574- prev = kids′[rexpr_idx - 1 ]
3575- if ! is_leaf (prev)
3576- @assert ! (kind (last_leaf (prev)) in KSet " Whitespace NewlineWs" )
3577- end
3578- end
3579- # Check whether there are whitespace we need to overwrite
3580- if kmatch (kids′, KSet " Whitespace" , rexpr_idx - 1 )
3581- # The previous node is whitespace
3582- spn = span (popat! (kids′, rexpr_idx - 1 ))
3583- seek (ctx. fmt_io, position (ctx. fmt_io) - spn)
3584- rexpr_idx -= 1
3585- @assert kind (first_leaf (rexpr)) != = K " Whitespace"
3586- end
3587- @assert kind (first_leaf (rexpr)) != = K " Whitespace"
3588- nl = " \n " * " " ^ (4 * ctx. indent_level)
3589- nlnode = Node (JuliaSyntax. SyntaxHead (K " NewlineWs" , JuliaSyntax. TRIVIA_FLAG), sizeof (nl))
3590- insert! (kids′, rexpr_idx, nlnode)
3591- rexpr_idx += 1
3592- replace_bytes! (ctx, nl, spn)
3593- accept_node! (ctx, nlnode)
3594- end
3595- ret = return_node (ctx, rexpr)
3596- kids′[rexpr_idx] = ret
3597- return make_node (node, kids′)
3598- elseif kind (rexpr) in KSet " for while"
3599- # For `for` and `while` loops we add `return` after the block.
3600- @assert kind (kids′[end ]) === K " NewlineWs"
3601- @assert kind (last_leaf (rexpr)) === K " end"
3602- insert_idx = lastindex (kids)
3603- kids′ = kids′ === kids ? copy (kids) : kids′
3604- for i in 1 : (insert_idx - 1 )
3605- accept_node! (ctx, kids′[i])
3606- end
3607- # Insert newline
3608- nl = " \n " * " " ^ (4 * ctx. indent_level)
3609- nlnode = Node (JuliaSyntax. SyntaxHead (K " NewlineWs" , JuliaSyntax. TRIVIA_FLAG), sizeof (nl))
3610- insert! (kids′, insert_idx, nlnode)
3611- replace_bytes! (ctx, nl, 0 )
3612- accept_node! (ctx, nlnode)
3613- # Insert `return`
3614- replace_bytes! (ctx, " return" , 0 )
3615- retnode = Node (
3616- JuliaSyntax. SyntaxHead (K " return" , 0 ), [
3617- Node (JuliaSyntax. SyntaxHead (K " return" , 0 ), 6 ),
3618- ]
3619- )
3620- insert! (kids′, insert_idx + 1 , retnode)
3621- return make_node (node, kids′)
3622- else
3623- # error("Unhandled node in explicit_return_block: $(kind(rexpr))")
3624- end
3625- return nothing
3626- end
3627-
3628- function explicit_return (ctx:: Context , node:: Node )
3629- if ! (! is_leaf (node) && kind (node) in KSet " function macro" )
3630- return nothing
3631- end
3632- if ! safe_to_insert_return (ctx, node)
3633- return nothing
3634- end
3635- kids = verified_kids (node)
3636- pos = position (ctx. fmt_io)
3637- block_idx = findlast (x -> kind (x) === K " block" , verified_kids (node))
3638- block_idx === nothing && return nothing
3639- for i in 1 : (block_idx - 1 )
3640- accept_node! (ctx, kids[i])
3641- end
3642- block′ = explicit_return_block (ctx, kids[block_idx])
3643- seek (ctx. fmt_io, pos)
3644- block′ === nothing && return nothing
3645- kids′ = copy (kids)
3646- kids′[block_idx] = block′
3647- return make_node (node, kids′)
3648- end
0 commit comments