Repository: JuliaLang/julia
File: stdlib/REPL/src/REPLCompletions.jl (Julia)

Code before:
# This needs to be a separate non-inlined function, see #19441
@noinline function find_dict_matches(identifier::AbstractDict, partial_key)
    matches = String[]
    for key in keys(identifier)
        rkey = repr(key)
        startswith(rkey,partial_key) && push!(matches,rkey)
    end
    return matches
end

# Provide completion for keyword arguments in function calls
# Returns true if the current argument must be a keyword because the cursor is beyond the semicolon
function complete_keyword_argument!(suggestions::Vector{Completion},
                                    ex::Expr, last_word::String,
                                    context_module::Module,
                                    arg_pos::Symbol; shift::Bool=false)
    kwargs_flag, funct, args_ex, kwargs_ex = _complete_methods(ex, context_module, true)::Tuple{Int, Any, Vector{Any}, Set{Symbol}}
    kwargs_flag == 2 && return false # one of the previous kwargs is invalid

    methods = Completion[]
    # Limit kwarg completions to cases when function is concretely known; looking up
    # matching methods for abstract functions — particularly `Any` or `Function` — can
    # take many seconds to run over the thousands of possible methods. Note that
    # isabstracttype would return naively return true for common constructor calls
    # like Array, but the REPL's introspection here may know their Type{T}.
    isconcretype(funct) || return false
    complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, -1, arg_pos == :kwargs)
    # TODO: use args_ex instead of Any[Vararg{Any}] and only provide kwarg completion for
    # method calls compatible with the current arguments.

    # For each method corresponding to the function call, provide completion suggestions
    # for each keyword that starts like the last word and that is not already used
    # previously in the expression. The corresponding suggestion is "kwname=".
    # If the keyword corresponds to an existing name, also include "kwname" as a suggestion
    # since the syntax "foo(; kwname)" is equivalent to "foo(; kwname=kwname)".
    kwargs = Set{String}()
    for m in methods
        # if MAX_METHOD_COMPLETIONS is hit a single TextCompletion is return by complete_methods! with an explanation
        # which can be ignored here
        m isa TextCompletion && continue
        m::MethodCompletion
        possible_kwargs = Base.kwarg_decl(m.method)
        current_kwarg_candidates = String[]
        for _kw in possible_kwargs
            kw = String(_kw)
            # HACK: Should consider removing current arg from AST.
            if !endswith(kw, "...") && startswith(kw, last_word) && (_kw ∉ kwargs_ex || kw == last_word)
                push!(current_kwarg_candidates, kw)
            end
        end
        union!(kwargs, current_kwarg_candidates)

Review comment (suggestion):
```suggestion
    isconcretetype(funct) || return false
```

Code after:
# This needs to be a separate non-inlined function, see #19441
@noinline function find_dict_matches(identifier::AbstractDict, partial_key)
    matches = String[]
    for key in keys(identifier)
        rkey = repr(key)
        startswith(rkey,partial_key) && push!(matches,rkey)
    end
    return matches
end

# Provide completion for keyword arguments in function calls
# Returns true if the current argument must be a keyword because the cursor is beyond the semicolon
function complete_keyword_argument!(suggestions::Vector{Completion},
                                    ex::Expr, last_word::String,
                                    context_module::Module,
                                    arg_pos::Symbol; shift::Bool=false)
    kwargs_flag, funct, args_ex, kwargs_ex = _complete_methods(ex, context_module, true)::Tuple{Int, Any, Vector{Any}, Set{Symbol}}
    kwargs_flag == 2 && return false # one of the previous kwargs is invalid

    methods = Completion[]
    # Limit kwarg completions to cases when function is concretely known; looking up
    # matching methods for abstract functions — particularly `Any` or `Function` — can
    # take many seconds to run over the thousands of possible methods. Note that
    # isabstracttype would return naively return true for common constructor calls
    # like Array, but the REPL's introspection here may know their Type{T}.
    isconcretetype(funct) || return false
    complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, -1, arg_pos == :kwargs)
    # TODO: use args_ex instead of Any[Vararg{Any}] and only provide kwarg completion for
    # method calls compatible with the current arguments.

    # For each method corresponding to the function call, provide completion suggestions
    # for each keyword that starts like the last word and that is not already used
    # previously in the expression. The corresponding suggestion is "kwname=".
    # If the keyword corresponds to an existing name, also include "kwname" as a suggestion
    # since the syntax "foo(; kwname)" is equivalent to "foo(; kwname=kwname)".
    kwargs = Set{String}()
    for m in methods
        # if MAX_METHOD_COMPLETIONS is hit a single TextCompletion is return by complete_methods! with an explanation
        # which can be ignored here
        m isa TextCompletion && continue
        m::MethodCompletion
        possible_kwargs = Base.kwarg_decl(m.method)
        current_kwarg_candidates = String[]
        for _kw in possible_kwargs
            kw = String(_kw)
            # HACK: Should consider removing current arg from AST.
            if !endswith(kw, "...") && startswith(kw, last_word) && (_kw ∉ kwargs_ex || kw == last_word)
                push!(current_kwarg_candidates, kw)
            end
        end
        union!(kwargs, current_kwarg_candidates)