Skip to content

Commit 97e2d12

Browse files
committed
Added so JuliaLang#7714 also takes care of args... when considering a match and
removed the requirement of equal lengths of args. The match also takes into account that parametric methods args needs to have the same type for one tvar using typeintersect. There is also added test of `show_method_candidates`.
1 parent 7f915c7 commit 97e2d12

File tree

3 files changed

+92
-17
lines changed

3 files changed

+92
-17
lines changed

base/replutil.jl

+51-16
Original file line numberDiff line numberDiff line change
@@ -165,27 +165,62 @@ function showerror(io::IO, ex::MethodError)
165165
print(io, "since type constructors fall back to convert methods in julia v0.4.")
166166
end
167167

168-
# Display up to three closest candidates
168+
show_method_candidates(io, ex)
169+
end
170+
171+
function show_method_candidates(io::IO, ex::MethodError)
172+
# Displays the closest candidates of the given function by looping over the
173+
# functions methods and counting the number of matching arguments.
169174
lines = Array((IOBuffer, Int), 0)
175+
name = isgeneric(ex.f) ? ex.f.env.name : :anonymous
170176
for method in methods(ex.f)
171-
n = length(ex.args)
172-
if n != length(method.sig)
173-
continue
174-
end
175177
buf = IOBuffer()
176-
print(buf, " $(ex.f.env.name)(")
177-
first = true
178+
print(buf, " $name")
178179
right_matches = 0
179-
for (arg, sigtype) in Zip2{Any,Any}(ex.args, method.sig)
180-
if first
181-
first = false
180+
tv = method.tvars
181+
if !isa(tv,Tuple)
182+
tv = (tv,)
183+
end
184+
if !isempty(tv)
185+
show_delim_array(buf, tv, '{', ',', '}', false)
186+
end
187+
print(buf, "(")
188+
t_i = Any[typeof(ex.args)...]
189+
right_matches = 0
190+
for i = 1 : min(length(t_i), length(method.sig))
191+
i != 1 && print(buf, ", ")
192+
# If isvarargtype then it checks wether the rest of the input arguements matches
193+
# the varargtype
194+
j = Base.isvarargtype(method.sig[i]) ? length(t_i) : i
195+
# checks if the type of arg 1:i of the input intersects with the current method
196+
t_in = typeintersect(method.sig[1:i], tuple(t_i[1:j]...))
197+
if t_in == None
198+
# If there is no typeintersect then the type signature from the method is
199+
# inserted in t_i this insures if the type at the next i matches the type
200+
# signature then there will be a type intersect
201+
t_i[i] = method.sig[i]
202+
Base.with_output_color(:red, buf) do buf
203+
print(buf, "::$(method.sig[i])")
204+
end
182205
else
183-
print(buf, ", ")
206+
right_matches += j==i ? 1 : 0
207+
print(buf, "::$(method.sig[i])")
184208
end
185-
if typeof(arg) <: sigtype
186-
right_matches += 1
187-
print(buf, "::$(sigtype)")
188-
else
209+
end
210+
if length(t_i) > length(method.sig) && Base.isvarargtype(method.sig[end])
211+
# It insures that methods like f(a::AbstractString...) gets the correct
212+
# number of right_matches
213+
for t in typeof(ex.args)[length(method.sig):end]
214+
if t <: method.sig[end].parameters[1]
215+
right_matches += 1
216+
end
217+
end
218+
end
219+
if length(t_i) < length(method.sig)
220+
# If the methods args is longer than input then the method
221+
# arguments is printed as not a match
222+
for sigtype in method.sig[length(t_i)+1:end]
223+
print(buf, ", ")
189224
Base.with_output_color(:red, buf) do buf
190225
print(buf, "::$(sigtype)")
191226
end
@@ -196,7 +231,7 @@ function showerror(io::IO, ex::MethodError)
196231
push!(lines, (buf, right_matches))
197232
end
198233
end
199-
if length(lines) != 0
234+
if length(lines) != 0 # Display up to three closest candidates
200235
Base.with_output_color(:normal, io) do io
201236
println(io, "\nClosest candidates are:")
202237
sort!(lines, by = x -> -x[2])

test/replutil.jl

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
function test_have_color(buf, color, no_color)
2+
if Base.have_color
3+
@test takebuf_string(buf) == color
4+
else
5+
@test takebuf_string(buf) == no_color
6+
end
7+
end
8+
let
9+
fe(x::Int, s::AbstractString...) = pass
10+
buf = IOBuffer()
11+
Base.show_method_candidates(buf, Base.MethodError(fe,(1.,1,"")))
12+
no_color = "\nClosest candidates are:\n fe(::Int64, ::AbstractString...)\n"
13+
test_have_color(buf,
14+
"\e[0m\nClosest candidates are:\n fe(\e[1m\e[31m::Int64\e[0m, \e[1m\e[31m::AbstractString...\e[0m)\n\e[0m",
15+
no_color)
16+
17+
Base.show_method_candidates(buf, Base.MethodError(fe,(1.,"","")))
18+
test_have_color(buf,
19+
"\e[0m\nClosest candidates are:\n fe(\e[1m\e[31m::Int64\e[0m, ::AbstractString...)\n\e[0m",
20+
no_color)
21+
22+
# should match
23+
Base.show_method_candidates(buf, Base.MethodError(fe,(1,"","")))
24+
test_have_color(buf,
25+
"\e[0m\nClosest candidates are:\n fe(::Int64, ::AbstractString...)\n\e[0m",
26+
no_color)
27+
28+
# Have no matches so should return empty
29+
Base.show_method_candidates(buf, Base.MethodError(fe,(1.,1,1)))
30+
test_have_color(buf, "", "")
31+
32+
ge(x::Int, args...) = pass
33+
ge(x::Int, y::Float64 ,args...) = pass
34+
ge(x::Int, y::Float64) = pass
35+
ge{T<:Real}(x::T, y::T, z::T) = pass
36+
Base.show_method_candidates(buf, Base.MethodError(ge,(1.,1.,2)))
37+
color = "\e[0m\nClosest candidates are:\n ge(\e[1m\e[31m::Int64\e[0m, ::Float64, ::Any...)\n ge(\e[1m\e[31m::Int64\e[0m, ::Any...)\n ge{T<:Real}(::T<:Real, ::T<:Real, \e[1m\e[31m::T<:Real\e[0m)\n ...\n\e[0m"
38+
no_color = no_color = "\nClosest candidates are:\n ge(::Int64, ::Float64, ::Any...)\n ge(::Int64, ::Any...)\n ge{T<:Real}(::T<:Real, ::T<:Real, ::T<:Real)\n ...\n"
39+
test_have_color(buf, color, no_color)
40+
end

test/runtests.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ testnames = [
99
"resolve", "pollfd", "mpfr", "broadcast", "complex", "socket",
1010
"floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics",
1111
"sysinfo", "rounding", "ranges", "mod2pi", "euler", "show",
12-
"lineedit", "replcompletions", "repl", "sets", "test", "goto",
12+
"lineedit", "replcompletions", "repl", "replutil", "sets", "test", "goto",
1313
"llvmcall", "grisu", "nullable", "meta", "profile",
1414
"libgit2", "docs", "base64", "parser"
1515
]

0 commit comments

Comments
 (0)