@@ -40,6 +40,7 @@ struct MethodCompletion <: Completion
4040 func
4141 input_types:: Type
4242 method:: Method
43+ orig_method:: Union{Nothing,Method} # if `method` is a keyword method, keep the original method for sensible printing
4344end
4445
4546struct BslashCompletion <: Completion
@@ -89,7 +90,7 @@ _completion_text(c::ModuleCompletion) = c.mod
8990_completion_text (c:: PackageCompletion ) = c. package
9091_completion_text (c:: PropertyCompletion ) = string (c. property)
9192_completion_text (c:: FieldCompletion ) = string (c. field)
92- _completion_text (c:: MethodCompletion ) = sprint (io -> show (io, c . method))
93+ _completion_text (c:: MethodCompletion ) = sprint (io -> show (io, isnothing (c . orig_method) ? c . method : c . orig_method :: Method ))
9394_completion_text (c:: BslashCompletion ) = c. bslash
9495_completion_text (c:: ShellCompletion ) = c. text
9596_completion_text (c:: DictCompletion ) = c. key
314315function should_method_complete (s:: AbstractString )
315316 method_complete = false
316317 for c in reverse (s)
317- if c in [' ,' , ' (' ]
318+ if c in [' ,' , ' (' , ' ; ' ]
318319 method_complete = true
319320 break
320321 elseif ! (c in whitespace_chars)
@@ -465,34 +466,58 @@ end
465466
466467# Method completion on function call expression that look like :(max(1))
467468function complete_methods (ex_org:: Expr , context_module:: Module = Main)
468- args_ex = Any[]
469469 func, found = get_value (ex_org. args[1 ], context_module):: Tuple{Any,Bool}
470470 ! found && return Completion[]
471471
472472 funargs = ex_org. args[2 : end ]
473473 # handle broadcasting, but only handle number of arguments instead of
474474 # argument types
475+ args_ex = Any[]
476+ kwargs_ex = Pair{Symbol,Any}[]
475477 if ex_org. head === :. && ex_org. args[2 ] isa Expr
476478 for _ in (ex_org. args[2 ]:: Expr ). args
477479 push! (args_ex, Any)
478480 end
479481 else
480482 for ex in funargs
481- val, found = get_type (ex, context_module)
482- push! (args_ex, val)
483+ if isexpr (ex, :parameters )
484+ for x in ex. args
485+ n, v = isexpr (x, :kw ) ? (x. args... ,) : (x, x)
486+ push! (kwargs_ex, n => first (get_type (v, context_module)))
487+ end
488+ elseif isexpr (ex, :kw )
489+ n, v = (ex. args... ,)
490+ push! (kwargs_ex, n => first (get_type (v, context_module)))
491+ else
492+ push! (args_ex, first (get_type (ex, context_module)))
493+ end
483494 end
484495 end
485496
486497 out = Completion[]
487- t_in = Tuple{Core. Typeof (func), args_ex... } # Input types
488- na = length (args_ex)+ 1
489498 ml = methods (func)
490- for method in ml
499+ # Input types and number of arguments
500+ if isempty (kwargs_ex)
501+ t_in = Tuple{Core. Typeof (func), args_ex... }
502+ na = length (t_in. parameters):: Int
503+ orig_ml = fill (nothing , length (ml))
504+ else
505+ isdefined (ml. mt, :kwsorter ) || return out
506+ kwfunc = ml. mt. kwsorter
507+ kwargt = NamedTuple{(first .(kwargs_ex)... ,), Tuple{last .(kwargs_ex)... }}
508+ t_in = Tuple{Core. Typeof (kwfunc), kwargt, Core. Typeof (func), args_ex... }
509+ na = length (t_in. parameters):: Int
510+ orig_ml = ml # this method is supposed to be used for printing
511+ ml = methods (kwfunc)
512+ func = kwfunc
513+ end
514+
515+ for (method:: Method , orig_method) in zip (ml, orig_ml)
491516 ms = method. sig
492517
493518 # Check if the method's type signature intersects the input types
494- if typeintersect (Base. rewrap_unionall (Tuple{(Base. unwrap_unionall (ms):: DataType ). parameters[1 : min (na, end )]. .. }, ms), t_in) != = Union{}
495- push! (out, MethodCompletion (func, t_in, method))
519+ if typeintersect (Base. rewrap_unionall (Tuple{(Base. unwrap_unionall (ms):: DataType ). parameters[1 : min (na, end )]. .. }, ms), t_in) != Union{}
520+ push! (out, MethodCompletion (func, t_in, method, orig_method ))
496521 end
497522 end
498523 return out
0 commit comments