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