Skip to content

Commit

Permalink
More tests for REPL completion of possibly ambiguous method calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Liozou committed Dec 28, 2021
1 parent 02960bc commit 27f8d56
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
7 changes: 4 additions & 3 deletions stdlib/REPL/src/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,10 @@ function complete_methods!(out::Vector{Completion}, @nospecialize(func), args_ex
most_specific = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), intersec, typemax(UInt))
# `most_specific == method` indicates that there is no strictly more specific
# method signature for these input types.
# `isnothing(most_specific)` indicates that the completed function call will
# not actually work. This can happen in case of method ambiguity.
# The completion is kept since it can be helpful to debug such ambiguity errors
# `isnothing(most_specific)` indicates that the completed function invoke will
# not actually work. This can happen in case of method ambiguity, or if the
# inferred argument types are not tight enough, which would make an invoke
# error because of the ambiguity, but the concrete function call still work.
if isnothing(most_specific) || (most_specific::Method) == method
push!(out, MethodCompletion(func, t_in, method, orig_method))
end
Expand Down
56 changes: 56 additions & 0 deletions stdlib/REPL/test/replcompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ let ex = quote
test10(a, d::Integer, z::Signed...) = pass
test10(s::String...) = pass

test11(a::Integer, b, c) = pass
test11(u, v::Integer, w) = pass
test11(x::Int, y::Int, z) = pass
test11(_, _, s::String) = pass

kwtest(; x=1, y=2, w...) = pass
kwtest2(a; x=1, y=2, w...) = pass

Expand Down Expand Up @@ -655,6 +660,57 @@ let s = "CompletionFoo.test10(\"a\", Union{Signed,Bool,String}[3][1], "
@test !any(str->occursin("test10(a::Integer, b::Integer, c)", str), c)
end

# Test method completion with ambiguity
let s = "CompletionFoo.test11(Integer[false][1], Integer[14][1], "
c, r, res = test_complete(s)
@test !res
@test length(c) == 4
@test all(startswith("test11("), c)
@test allunique(c)
end

let s = "CompletionFoo.test11(Integer[-7][1], Integer[0x6][1], 6,"
c, r, res = test_complete(s)
@test !res
@test length(c) == 3
@test any(str->occursin("test11(a::Integer, b, c)", str), c)
@test any(str->occursin("test11(u, v::Integer, w)", str), c)
@test any(str->occursin("test11(x::$Int, y::$Int, z)", str), c)
end

let s = "CompletionFoo.test11(3, 4,"
c, r, res = test_complete(s)
@test !res
@test length(c) == 2
@test any(str->occursin("test11(x::$Int, y::$Int, z)", str), c)
@test any(str->occursin("test11(::Any, ::Any, s::String)", str), c)
end

let s = "CompletionFoo.test11(0x8, 5,"
c, r, res = test_complete(s)
@test !res
@test length(c) == 3
@test any(str->occursin("test11(a::Integer, b, c)", str), c)
@test any(str->occursin("test11(u, v::Integer, w)", str), c)
@test any(str->occursin("test11(::Any, ::Any, s::String)", str), c)
end

let s = "CompletionFoo.test11(0x8, 'c',"
c, r, res = test_complete(s)
@test !res
@test length(c) == 2
@test any(str->occursin("test11(a::Integer, b, c)", str), c)
@test any(str->occursin("test11(::Any, ::Any, s::String)", str), c)
end

let s = "CompletionFoo.test11('d', 3,"
c, r, res = test_complete(s)
@test !res
@test length(c) == 2
@test any(str->occursin("test11(u, v::Integer, w)", str), c)
@test any(str->occursin("test11(::Any, ::Any, s::String)", str), c)
end

# Test of inference based getfield completion
let s = "(1+2im)."
c,r = test_complete(s)
Expand Down

0 comments on commit 27f8d56

Please sign in to comment.