Skip to content

Commit 63bbeaa

Browse files
authored
Support Core.kwcall (#105)
Keyword dispatch methods went away in Julia 1.9, replaced by the generic `kwcall`. In #102 I disabled the corresponding test. That was misguided because we still want to be able to recover the source definition, regardless of the details of the underlying implementation.
1 parent 5aa2d96 commit 63bbeaa

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

src/CodeTracking.jl

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,28 +219,48 @@ see [`definition(Expr, method::Method)`](@ref) instead.
219219
See also [`code_string`](@ref).
220220
"""
221221
function definition(::Type{String}, method::Method)
222+
methodname = method.name
223+
if methodname == :kwcall # Julia 1.9+
224+
# it seems better to have nkw, but see https://github.com/JuliaLang/julia/issues/48786
225+
# The first `::typeof(f)` seems possibly unsafe because some kwargs could themselves function-typed
226+
# Nevertheless this is our best hope.
227+
p = Base.unwrap_unionall(method.sig).parameters
228+
for i = 2:length(p)
229+
T = p[i]
230+
if T <: Function
231+
mstring = string(nameof(T))
232+
if startswith(mstring, '#')
233+
methodname = Symbol(mstring[2:end])
234+
break
235+
end
236+
end
237+
end
238+
methodname == :kwcall && error("could not identify method name in `Core.kwcall`")
239+
end
222240
file, line = whereis(method)
223241
line == 0 && return nothing
224-
src = src_from_file_or_REPL(file)
242+
src = src_from_file_or_REPL(file) # whole file contents
225243
src === nothing && return nothing
226244
src = replace(src, "\r"=>"")
245+
# Step forward to the definition of this method, keeping track of positions of newlines
227246
eol = isequal('\n')
228247
linestarts = Int[]
229248
istart = 1
230-
for i = 1:line-1
249+
for _ = 1:line-1
231250
push!(linestarts, istart)
232251
istart = findnext(eol, src, istart) + 1
233252
end
253+
# Parse the function definition (hoping that we've found the right location to start)
234254
ex, iend = Meta.parse(src, istart; raise=false)
235255
iend = prevind(src, iend)
236-
if isfuncexpr(ex, method.name)
256+
if isfuncexpr(ex, methodname)
237257
iend = min(iend, lastindex(src))
238258
return strip(src[istart:iend], '\n'), line
239259
end
240260
# The function declaration was presumably on a previous line
241261
lineindex = lastindex(linestarts)
242262
linestop = max(0, lineindex - 20)
243-
while !isfuncexpr(ex, method.name) && lineindex > linestop
263+
while !isfuncexpr(ex, methodname) && lineindex > linestop
244264
istart = linestarts[lineindex]
245265
try
246266
ex, iend = Meta.parse(src, istart)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ struct Functor end
300300
@test body == "(::Functor)(x, y) = x+y"
301301
end
302302

303-
if v"1.6" <= VERSION < v"1.9-beta"
303+
if v"1.6" <= VERSION
304304
@testset "kwfuncs" begin
305305
body, _ = CodeTracking.definition(String, @which fkw(; x=1))
306306
@test body == """

0 commit comments

Comments
 (0)