diff --git a/base/methodshow.jl b/base/methodshow.jl index 68bfa5df750fa..18bd7dfccd3b8 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -119,8 +119,25 @@ end # In case the line numbers in the source code have changed since the code was compiled, # allow packages to set a callback function that corrects them. # (Used by Revise and perhaps other packages.) -default_methodloc(method::Method) = method.file, method.line -const methodloc_callback = Ref{Function}(default_methodloc) +const methodloc_callback = Ref{Union{Function, Nothing}}(nothing) + +# This function does the method location updating +function updated_methodloc(m::Method)::Tuple{String, Int32} + file, line = m.file, m.line + if methodloc_callback[] !== nothing + try + file, line = invokelatest(methodloc_callback[], m) + catch + end + end + # The file defining Base.Sys gets included after this file is included so make sure + # this function is valid even in this intermediary state + if isdefined(@__MODULE__, :Sys) && Sys.BUILD_STDLIB_PATH != Sys.STDLIB + # BUILD_STDLIB_PATH gets defined in sysinfo.jl + file = replace(string(file), normpath(Sys.BUILD_STDLIB_PATH) => normpath(Sys.STDLIB)) + end + return string(file), line +end functionloc(m::Core.MethodInstance) = functionloc(m.def) @@ -130,7 +147,7 @@ functionloc(m::Core.MethodInstance) = functionloc(m.def) Returns a tuple `(filename,line)` giving the location of a `Method` definition. """ function functionloc(m::Method) - file, ln = invokelatest(methodloc_callback[], m) + file, ln = updated_methodloc(m) if ln <= 0 error("could not determine location of method definition") end @@ -195,10 +212,7 @@ function show(io::IO, m::Method) show_method_params(io, tv) print(io, " in ", m.module) if line > 0 - try - file, line = invokelatest(methodloc_callback[], m) - catch - end + file, line = updated_methodloc(m) print(io, " at ", file, ":", line) end end @@ -247,11 +261,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru println(io) print(io, "[$(n)] ") show(io, meth) - file, line = meth.file, meth.line - try - file, line = invokelatest(methodloc_callback[], meth) - catch - end + file, line = updated_methodloc(meth) push!(LAST_SHOWN_LINE_INFOS, (string(file), line)) else rest += 1 @@ -361,10 +371,7 @@ function show(io::IO, ::MIME"text/html", m::Method) end print(io, " in ", m.module) if line > 0 - try - file, line = invokelatest(methodloc_callback[], m) - catch - end + file, line = updated_methodloc(m) u = url(m) if isempty(u) print(io, " at ", file, ":", line) @@ -398,11 +405,7 @@ function show(io::IO, mime::MIME"text/plain", mt::AbstractVector{Method}) first = false print(io, "[$(i)] ") show(io, m) - file, line = m.file, m.line - try - file, line = invokelatest(methodloc_callback[], m) - catch - end + file, line = updated_methodloc(m) push!(LAST_SHOWN_LINE_INFOS, (string(file), line)) end end diff --git a/base/sysinfo.jl b/base/sysinfo.jl index df71537ad05f5..e9b454ebdaf66 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -49,6 +49,9 @@ A string containing the full path to the directory containing the `julia` execut A string containing the full path to the directory containing the `stdlib` packages. """ STDLIB = "$BINDIR/../share/julia/stdlib/v$(VERSION.major).$(VERSION.minor)" # for bootstrap +# In case STDLIB change after julia is built, the variable below can be used +# to update cached method locations to updated ones. +const BUILD_STDLIB_PATH = STDLIB # helper to avoid triggering precompile warnings diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index 3e522ce24a54e..afe63cd0d5949 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -389,3 +389,7 @@ if Sys.iswindows() || Sys.isapple() @test clipboard() == str end end + +# buildbot path updating +file, ln = functionloc(versioninfo, Tuple{}) +@test isfile(file) diff --git a/test/show.jl b/test/show.jl index 06ee3bc579fa6..9a6c2c8a6e4c3 100644 --- a/test/show.jl +++ b/test/show.jl @@ -637,7 +637,6 @@ else end # Method location correction (Revise integration) -methloc = Base.methodloc_callback[] dummyloc(m::Method) = :nofile, 123456789 Base.methodloc_callback[] = dummyloc let repr = sprint(show, "text/plain", methods(Base.inbase)) @@ -646,7 +645,7 @@ end let repr = sprint(show, "text/html", methods(Base.inbase)) @test occursin("nofile:123456789", repr) end -Base.methodloc_callback[] = methloc +Base.methodloc_callback[] = nothing @testset "matrix printing" begin # print_matrix should be able to handle small and large objects easily, test by