diff --git a/src/Observables.jl b/src/Observables.jl index 5feeb36..29b0018 100644 --- a/src/Observables.jl +++ b/src/Observables.jl @@ -546,4 +546,19 @@ include("macros.jl") @deprecate notify! notify +# Look up the source location of `do` block Observable MethodInstances +function methodlist(@nospecialize(ft::Type)) + if ft <: OnUpdate + ft = Base.unwrap_unionall(Base.unwrap_unionall(ft).parameters[1]) + if ft <: MapUpdater + ft = Base.unwrap_unionall(Base.unwrap_unionall(ft).parameters[1]) + end + end + return Base.MethodList(ft.name.mt) +end + +methodlist(mi::Core.MethodInstance) = methodlist(Base.unwrap_unionall(mi.specTypes).parameters[1]) +methodlist(obsf::ObserverFunction) = methodlist(obsf.f) +methodlist(@nospecialize(f::Function)) = methodlist(typeof(f)) + end # module diff --git a/test/runtests.jl b/test/runtests.jl index 5b6ed93..9067ac6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -379,6 +379,34 @@ end @test obs_copy[] == 1 end +@testset "methodlist" begin + _only(list) = (@assert length(list) == 1; return list[1]) # `only` is avail in Julia 1.4+ + obs = Observable(1) + obsf = on(obs) do x + x + 1 + end + line1 = -2 + @__LINE__ + obs2 = map(obs) do x + x + 1 + end + line2 = -2 + @__LINE__ + obsflist = onany(obs, 5) do x, y + x + y + end + line3 = -2 + @__LINE__ + obsf2 = _only(obsflist) + m = _only(Observables.methodlist(obsf).ms) + @test occursin("runtests.jl:$line1", string(m)) + m = _only(Observables.methodlist(obsf.f).ms) + @test occursin("runtests.jl:$line1", string(m)) + m = _only(Observables.methodlist(obs.listeners[2]).ms) + @test occursin("runtests.jl:$line2", string(m)) + m = _only(Observables.methodlist(obsf2).ms) + @test occursin("runtests.jl:$line3", string(m)) + obsf3 = on(sqrt, obs) + @test Observables.methodlist(obsf3).mt.name === :sqrt +end + @testset "deprecations" begin a = Observable(1) b = @test_deprecated map(sqrt, a; init=13.0)