From a45ddd4529f7e59f8a8baf4ccec29b46accf8b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Fri, 18 Apr 2025 12:40:04 -0400 Subject: [PATCH 01/15] Parametrize method_info by (mt, sig) --- src/CodeTracking.jl | 17 ++++++++++------- src/utils.jl | 4 ++-- test/runtests.jl | 5 +++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/CodeTracking.jl b/src/CodeTracking.jl index 585c2ec..98130eb 100644 --- a/src/CodeTracking.jl +++ b/src/CodeTracking.jl @@ -11,7 +11,7 @@ CodeTracking can be thought of as an extension of InteractiveUtils, and pairs we module CodeTracking using Base: PkgId -using Core: LineInfoNode +using Core: LineInfoNode, MethodTable using Base.Meta: isexpr using UUIDs using InteractiveUtils @@ -29,12 +29,12 @@ include("utils.jl") # These values get populated by Revise -# `method_info[sig]` is either: +# `method_info[mt => sig]` is either: # - `missing`, to indicate that the method cannot be located # - a list of `(lnn,ex)` pairs. In almost all cases there will be just one of these, # but "mistakes" in moving methods from one file to another can result in more than # definition. The last pair in the list is the currently-active definition. -const method_info = IdDict{Type,Union{Missing,Vector{Tuple{LineNumberNode,Expr}}}}() +const method_info = IdDict{Pair{<:Union{Nothing, MethodTable}, <:Type},Union{Missing,Vector{Tuple{LineNumberNode,Expr}}}}() const _pkgfiles = Dict{PkgId,PkgFiles}() @@ -58,6 +58,9 @@ const expressions_callback = Ref{Any}(nothing) const juliabase = joinpath("julia", "base") const juliastdlib = joinpath("julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)") +method_table(method::Method) = isdefined(method, :external_mt) ? method.external_mt::MethodTable : nothing +method_info_key(method::Method) = method_table(method) => method.sig + ### Public API """ @@ -70,13 +73,13 @@ the method declaration, otherwise it is the first line of the method's body. function whereis(method::Method) file, line = String(method.file), method.line startswith(file, "REPL[") && return file, line - lin = get(method_info, method.sig, nothing) + lin = get(method_info, method_info_key(method), nothing) if lin === nothing f = method_lookup_callback[] if f !== nothing try Base.invokelatest(f, method) - lin = get(method_info, method.sig, nothing) + lin = get(method_info, method_info_key(method), nothing) catch end end @@ -298,13 +301,13 @@ See also [`code_expr`](@ref). """ function definition(::Type{Expr}, method::Method) file = String(method.file) - def = startswith(file, "REPL[") ? nothing : get(method_info, method.sig, nothing) + def = startswith(file, "REPL[") ? nothing : get(method_info, method_info_key(method), nothing) if def === nothing f = method_lookup_callback[] if f !== nothing try Base.invokelatest(f, method) - def = get(method_info, method.sig, nothing) + def = get(method_info, method_info_key(method), nothing) catch end end diff --git a/src/utils.jl b/src/utils.jl index 8d3db2a..519db8c 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -400,5 +400,5 @@ getpkgid(uuid::UUID, libname) = PkgId(uuid, libname) # callers vulnerable to invalidation. These convenience utilities allow callers to insulate # themselves from invalidation. These are used by Revise. # example package triggering invalidation: StaticArrays (new `convert(Type{Array{T,N}}, ::AbstractArray)` methods) -invoked_setindex!(dct::IdDict{K,V}, @nospecialize(val), @nospecialize(key)) where {K,V} = Base.invokelatest(setindex!, dct, val, key)::typeof(dct) -invoked_get!(::Type{T}, dct::IdDict{K,V}, @nospecialize(key)) where {K,V,T<:V} = Base.invokelatest(get!, T, dct, key)::V +invoked_setindex!(dct::IdDict{K,V}, @nospecialize(val), @nospecialize(key)) where {K,V} = Base.invokelatest(setindex!, dct, val, convert(K, key))::typeof(dct) +invoked_get!(::Type{T}, dct::IdDict{K,V}, @nospecialize(key)) where {K,V,T<:V} = Base.invokelatest(get!, T, dct, convert(K, key))::V diff --git a/test/runtests.jl b/test/runtests.jl index c448802..f0e8860 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -101,7 +101,7 @@ isdefined(Main, :Revise) ? Main.Revise.includet("script.jl") : include("script.j # Test a method marked as missing m = @which sum(1:5) - CodeTracking.method_info[m.sig] = missing + CodeTracking.method_info[nothing => m.sig] = missing @test whereis(m) == (CodeTracking.maybe_fix_path(String(m.file)), m.line) @test definition(m) === nothing @@ -323,7 +323,8 @@ end Revise.add_revise_deps() sigs = signatures_at(CodeTracking, "src/utils.jl", 5) @test length(sigs) == 1 # only isn't available on julia 1.0 - @test first(sigs) == Tuple{typeof(CodeTracking.checkname), Expr, Any} + (mt, sig) = first(sigs) + @test sig == Tuple{typeof(CodeTracking.checkname), Expr, Any} @test pkgfiles(CodeTracking).id == Base.PkgId(CodeTracking) end From 821b1b4ca695fe7828646561afcdd63149dde9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Fri, 18 Apr 2025 13:32:09 -0400 Subject: [PATCH 02/15] Add tests --- test/runtests.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index f0e8860..db3ed6b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -455,3 +455,19 @@ end @test CodeTracking.strip_gensym("#𝓔′#90") == :𝓔′ @test CodeTracking.strip_gensym("𝓔′##kw") == :𝓔′ end + +if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :(var"@MethodTable")) + +@testset "External method tables" begin + mod = @eval module $(gensym(:ExternalMT)) + Base.Experimental.@MethodTable method_table + end + ex = :(Base.Experimental.@overlay method_table +(x::String, y::String) = x * y) + method = Core.eval(mod, ex) + lnn = LineNumberNode(Int(method.line), method.file) + @test CodeTracking.definition(Expr, method) === nothing + CodeTracking.method_info[method.external_mt => method.sig] = [(lnn, ex)] + @test CodeTracking.definition(Expr, method) == ex +end + +end From 45eb7c27ab8ba1228a02501eb44a6c54573a0b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 11:12:16 -0400 Subject: [PATCH 03/15] `sigs` => `mt_sigs` renaming --- test/runtests.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index db3ed6b..8c89a85 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -297,8 +297,8 @@ end @testset "With Revise" begin if isdefined(Main, :Revise) m = @which gcd(10, 20) - sigs = signatures_at(Base.find_source_file(String(m.file)), m.line) - @test !isempty(sigs) + mt_sigs = signatures_at(Base.find_source_file(String(m.file)), m.line) + @test !isempty(mt_sigs) ex = @code_expr(gcd(10, 20)) @test ex isa Expr body = ex.args[2] @@ -308,10 +308,10 @@ end if Base.VERSION < v"1.11.0-0" m = first(methods(edit)) - sigs = signatures_at(String(m.file), m.line) - @test !isempty(sigs) - sigs = signatures_at(Base.find_source_file(String(m.file)), m.line) - @test !isempty(sigs) + mt_sigs = signatures_at(String(m.file), m.line) + @test !isempty(mt_sigs) + mt_sigs = signatures_at(Base.find_source_file(String(m.file)), m.line) + @test !isempty(mt_sigs) end # issue #23 @@ -321,9 +321,9 @@ end if isdefined(Revise, :add_revise_deps) Revise.add_revise_deps() - sigs = signatures_at(CodeTracking, "src/utils.jl", 5) - @test length(sigs) == 1 # only isn't available on julia 1.0 - (mt, sig) = first(sigs) + mt_sigs = signatures_at(CodeTracking, "src/utils.jl", 5) + @test length(mt_sigs) == 1 # only isn't available on julia 1.0 + (mt, sig) = first(mt_sigs) @test sig == Tuple{typeof(CodeTracking.checkname), Expr, Any} @test pkgfiles(CodeTracking).id == Base.PkgId(CodeTracking) end From ba1b0ee38daf60812e01e209422683839e8e0f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 11:14:21 -0400 Subject: [PATCH 04/15] Bump major version to 2.0.0-DEV --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1d77231..78b17a5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "CodeTracking" uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" authors = ["Tim Holy "] -version = "1.3.9" +version = "2.0.0-DEV" [deps] InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" From ba33acb437693cd9d17ceda2bd594264c778286c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 11:47:39 -0400 Subject: [PATCH 05/15] Make the key type of `method_info` concrete --- src/CodeTracking.jl | 6 +++--- test/runtests.jl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CodeTracking.jl b/src/CodeTracking.jl index 98130eb..af14e4f 100644 --- a/src/CodeTracking.jl +++ b/src/CodeTracking.jl @@ -33,8 +33,8 @@ include("utils.jl") # - `missing`, to indicate that the method cannot be located # - a list of `(lnn,ex)` pairs. In almost all cases there will be just one of these, # but "mistakes" in moving methods from one file to another can result in more than -# definition. The last pair in the list is the currently-active definition. -const method_info = IdDict{Pair{<:Union{Nothing, MethodTable}, <:Type},Union{Missing,Vector{Tuple{LineNumberNode,Expr}}}}() +# one definition. The last pair in the list is the currently-active definition. +const method_info = IdDict{Pair{Union{Nothing, MethodTable}, Type},Union{Missing,Vector{Tuple{LineNumberNode,Expr}}}}() const _pkgfiles = Dict{PkgId,PkgFiles}() @@ -59,7 +59,7 @@ const juliabase = joinpath("julia", "base") const juliastdlib = joinpath("julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)") method_table(method::Method) = isdefined(method, :external_mt) ? method.external_mt::MethodTable : nothing -method_info_key(method::Method) = method_table(method) => method.sig +method_info_key(method::Method) = Pair{Union{Nothing, MethodTable}, Type}(method_table(method), method.sig) ### Public API diff --git a/test/runtests.jl b/test/runtests.jl index 8c89a85..4ab77a0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -101,7 +101,7 @@ isdefined(Main, :Revise) ? Main.Revise.includet("script.jl") : include("script.j # Test a method marked as missing m = @which sum(1:5) - CodeTracking.method_info[nothing => m.sig] = missing + CodeTracking.invoked_setindex!(CodeTracking.method_info, missing, nothing => m.sig) @test whereis(m) == (CodeTracking.maybe_fix_path(String(m.file)), m.line) @test definition(m) === nothing @@ -466,7 +466,7 @@ if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :(var"@MethodT method = Core.eval(mod, ex) lnn = LineNumberNode(Int(method.line), method.file) @test CodeTracking.definition(Expr, method) === nothing - CodeTracking.method_info[method.external_mt => method.sig] = [(lnn, ex)] + CodeTracking.invoked_setindex!(CodeTracking.method_info, [(lnn, ex)], method.external_mt => method.sig) @test CodeTracking.definition(Expr, method) == ex end From 6a2e3031fd857b51f21738b6ab6c50be44928a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 12:01:17 -0400 Subject: [PATCH 06/15] Define MethodInfoKey --- src/CodeTracking.jl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/CodeTracking.jl b/src/CodeTracking.jl index af14e4f..0e11566 100644 --- a/src/CodeTracking.jl +++ b/src/CodeTracking.jl @@ -34,7 +34,10 @@ include("utils.jl") # - a list of `(lnn,ex)` pairs. In almost all cases there will be just one of these, # but "mistakes" in moving methods from one file to another can result in more than # one definition. The last pair in the list is the currently-active definition. -const method_info = IdDict{Pair{Union{Nothing, MethodTable}, Type},Union{Missing,Vector{Tuple{LineNumberNode,Expr}}}}() + +const MethodInfoKey = Pair{Union{Nothing, MethodTable}, Type} + +const method_info = IdDict{MethodInfoKey,Union{Missing,Vector{Tuple{LineNumberNode,Expr}}}}() const _pkgfiles = Dict{PkgId,PkgFiles}() @@ -59,7 +62,7 @@ const juliabase = joinpath("julia", "base") const juliastdlib = joinpath("julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)") method_table(method::Method) = isdefined(method, :external_mt) ? method.external_mt::MethodTable : nothing -method_info_key(method::Method) = Pair{Union{Nothing, MethodTable}, Type}(method_table(method), method.sig) +MethodInfoKey(method::Method) = MethodInfoKey(method_table(method), method.sig) ### Public API @@ -73,13 +76,13 @@ the method declaration, otherwise it is the first line of the method's body. function whereis(method::Method) file, line = String(method.file), method.line startswith(file, "REPL[") && return file, line - lin = get(method_info, method_info_key(method), nothing) + lin = get(method_info, MethodInfoKey(method), nothing) if lin === nothing f = method_lookup_callback[] if f !== nothing try Base.invokelatest(f, method) - lin = get(method_info, method_info_key(method), nothing) + lin = get(method_info, MethodInfoKey(method), nothing) catch end end @@ -301,13 +304,13 @@ See also [`code_expr`](@ref). """ function definition(::Type{Expr}, method::Method) file = String(method.file) - def = startswith(file, "REPL[") ? nothing : get(method_info, method_info_key(method), nothing) + def = startswith(file, "REPL[") ? nothing : get(method_info, MethodInfoKey(method), nothing) if def === nothing f = method_lookup_callback[] if f !== nothing try Base.invokelatest(f, method) - def = get(method_info, method_info_key(method), nothing) + def = get(method_info, MethodInfoKey(method), nothing) catch end end From 1949618dfc09a24775ae4fe3d171d8a754ef1cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 12:25:30 -0400 Subject: [PATCH 07/15] Don't convert on invoked accessors As all other manipulation functions for IdDict don't convert, it's best to be consistent and catch errors when we detect a mismatch. --- src/utils.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 519db8c..8d3db2a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -400,5 +400,5 @@ getpkgid(uuid::UUID, libname) = PkgId(uuid, libname) # callers vulnerable to invalidation. These convenience utilities allow callers to insulate # themselves from invalidation. These are used by Revise. # example package triggering invalidation: StaticArrays (new `convert(Type{Array{T,N}}, ::AbstractArray)` methods) -invoked_setindex!(dct::IdDict{K,V}, @nospecialize(val), @nospecialize(key)) where {K,V} = Base.invokelatest(setindex!, dct, val, convert(K, key))::typeof(dct) -invoked_get!(::Type{T}, dct::IdDict{K,V}, @nospecialize(key)) where {K,V,T<:V} = Base.invokelatest(get!, T, dct, convert(K, key))::V +invoked_setindex!(dct::IdDict{K,V}, @nospecialize(val), @nospecialize(key)) where {K,V} = Base.invokelatest(setindex!, dct, val, key)::typeof(dct) +invoked_get!(::Type{T}, dct::IdDict{K,V}, @nospecialize(key)) where {K,V,T<:V} = Base.invokelatest(get!, T, dct, key)::V From 788b4ea7322bc4ec14938cb1bfddadbd0982a2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 12:26:43 -0400 Subject: [PATCH 08/15] Use `MethodInfoKey` instead of relying on implicit conversions --- test/runtests.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 4ab77a0..fb6654d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,7 +4,7 @@ using CodeTracking using Test, InteractiveUtils, REPL, LinearAlgebra, SparseArrays # Note: ColorTypes needs to be installed, but note the intentional absence of `using ColorTypes` -using CodeTracking: line_is_decl +using CodeTracking: line_is_decl, MethodInfoKey if !isempty(ARGS) && "revise" ∈ ARGS # For running tests with and without Revise @@ -101,7 +101,7 @@ isdefined(Main, :Revise) ? Main.Revise.includet("script.jl") : include("script.j # Test a method marked as missing m = @which sum(1:5) - CodeTracking.invoked_setindex!(CodeTracking.method_info, missing, nothing => m.sig) + CodeTracking.method_info[MethodInfoKey(nothing, m.sig)] = missing @test whereis(m) == (CodeTracking.maybe_fix_path(String(m.file)), m.line) @test definition(m) === nothing @@ -466,7 +466,7 @@ if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :(var"@MethodT method = Core.eval(mod, ex) lnn = LineNumberNode(Int(method.line), method.file) @test CodeTracking.definition(Expr, method) === nothing - CodeTracking.invoked_setindex!(CodeTracking.method_info, [(lnn, ex)], method.external_mt => method.sig) + CodeTracking.method_info[MethodInfoKey(method)] = [(lnn, ex)] @test CodeTracking.definition(Expr, method) == ex end From dc208c1f298f575f0dcfb55390b6467331ec36cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 14:57:42 -0400 Subject: [PATCH 09/15] Temporarily patch CI to test with Revise PR --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 243b45c..de20484 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,8 @@ jobs: julia -e ' using Pkg Pkg.develop(path=".") - Pkg.add("Revise") + pkg"add https://github.com/serenity4/JuliaInterpreter.jl#codetracking-v2 https://github.com/serenity4/LoweredCodeUtils.jl#support-external-methodtables https://github.com/serenity4/Revise.jl#revise-external-methodtables" + # Pkg.add("Revise") Pkg.test("Revise") ' - name: Test while running Revise From 5c677cf16edc204f8bedbd4111434db7761e99a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 15:13:42 -0400 Subject: [PATCH 10/15] Attempt to fix failing test --- test/runtests.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index fb6654d..1985f60 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -456,14 +456,19 @@ end @test CodeTracking.strip_gensym("𝓔′##kw") == :𝓔′ end -if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :(var"@MethodTable")) +@static if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :(var"@MethodTable")) @testset "External method tables" begin mod = @eval module $(gensym(:ExternalMT)) Base.Experimental.@MethodTable method_table end ex = :(Base.Experimental.@overlay method_table +(x::String, y::String) = x * y) - method = Core.eval(mod, ex) + if VERSION ≥ v"1.13-" + method = Core.eval(mod, ex) + else + Core.eval(mod, ex) + method = only(Base.MethodList(mod.method_table).ms) + end lnn = LineNumberNode(Int(method.line), method.file) @test CodeTracking.definition(Expr, method) === nothing CodeTracking.method_info[MethodInfoKey(method)] = [(lnn, ex)] From 20abb2b5bfaa5eb81fd7a5330535562e63d12bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Mon, 21 Apr 2025 16:34:36 -0400 Subject: [PATCH 11/15] Drop support for Julia < 1.10 --- .github/workflows/ci.yml | 2 +- Project.toml | 2 +- test/runtests.jl | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de20484..211a71d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false matrix: version: - - '1.6' # latest LTS + - 'lts' - '1' - 'pre' - 'nightly' diff --git a/Project.toml b/Project.toml index 78b17a5..20e8d75 100644 --- a/Project.toml +++ b/Project.toml @@ -8,7 +8,7 @@ InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] -julia = "1.6" +julia = "1.10" [extras] ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" diff --git a/test/runtests.jl b/test/runtests.jl index 1985f60..d3d3d04 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -456,8 +456,6 @@ end @test CodeTracking.strip_gensym("𝓔′##kw") == :𝓔′ end -@static if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :(var"@MethodTable")) - @testset "External method tables" begin mod = @eval module $(gensym(:ExternalMT)) Base.Experimental.@MethodTable method_table @@ -474,5 +472,3 @@ end CodeTracking.method_info[MethodInfoKey(method)] = [(lnn, ex)] @test CodeTracking.definition(Expr, method) == ex end - -end From 0ef1569705444f7bcf7f067496ca5389dcb10907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Thu, 24 Apr 2025 13:54:12 -0400 Subject: [PATCH 12/15] Use Base method to extract method table --- src/CodeTracking.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CodeTracking.jl b/src/CodeTracking.jl index 0e11566..9ac5e70 100644 --- a/src/CodeTracking.jl +++ b/src/CodeTracking.jl @@ -61,8 +61,7 @@ const expressions_callback = Ref{Any}(nothing) const juliabase = joinpath("julia", "base") const juliastdlib = joinpath("julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)") -method_table(method::Method) = isdefined(method, :external_mt) ? method.external_mt::MethodTable : nothing -MethodInfoKey(method::Method) = MethodInfoKey(method_table(method), method.sig) +MethodInfoKey(method::Method) = MethodInfoKey(Base.get_methodtable(method), method.sig) ### Public API From f973147add2c548cb3fa1b2fbe318aabb662e7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Thu, 24 Apr 2025 15:50:02 -0400 Subject: [PATCH 13/15] Revert "Use Base method to extract method table" This reverts commit 0ef1569705444f7bcf7f067496ca5389dcb10907. --- src/CodeTracking.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CodeTracking.jl b/src/CodeTracking.jl index 9ac5e70..0e11566 100644 --- a/src/CodeTracking.jl +++ b/src/CodeTracking.jl @@ -61,7 +61,8 @@ const expressions_callback = Ref{Any}(nothing) const juliabase = joinpath("julia", "base") const juliastdlib = joinpath("julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)") -MethodInfoKey(method::Method) = MethodInfoKey(Base.get_methodtable(method), method.sig) +method_table(method::Method) = isdefined(method, :external_mt) ? method.external_mt::MethodTable : nothing +MethodInfoKey(method::Method) = MethodInfoKey(method_table(method), method.sig) ### Public API From da3aae93fee0ac1fc04eeea9b7c0cc68997d32c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Fri, 25 Apr 2025 10:13:49 -0400 Subject: [PATCH 14/15] Update README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a599614..c3b9fd6 100644 --- a/README.md +++ b/README.md @@ -116,14 +116,16 @@ You can also find the method-signatures at a particular location: ```julia julia> signatures_at(ColorTypes, "src/traits.jl", 14) -1-element Array{Any,1}: - Tuple{typeof(red),AbstractRGB} +1-element Vector{Pair{Union{Nothing, Core.MethodTable}, Type}}: + nothing => Tuple{typeof(red),AbstractRGB} julia> signatures_at("/home/tim/.julia/packages/ColorTypes/BsAWO/src/traits.jl", 14) -1-element Array{Any,1}: - Tuple{typeof(red),AbstractRGB} +1-element Vector{Pair{Union{Nothing, Core.MethodTable}, Type}}: + nothing => Tuple{typeof(red),AbstractRGB} ``` +with the first element being the method table for which the method has been defined (a value of `nothing` denotes the default method table). + CodeTracking also helps correcting for [Julia issue #26314](https://github.com/JuliaLang/julia/issues/26314): ```julia From c0ca2ff0e1fe19b1640922ec028e9edaf1de9a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belmant?= Date: Fri, 25 Apr 2025 13:50:44 -0400 Subject: [PATCH 15/15] Revert changes to ci.yml Tests will fail, that's normal --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 211a71d..627ee17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,7 @@ jobs: julia -e ' using Pkg Pkg.develop(path=".") - pkg"add https://github.com/serenity4/JuliaInterpreter.jl#codetracking-v2 https://github.com/serenity4/LoweredCodeUtils.jl#support-external-methodtables https://github.com/serenity4/Revise.jl#revise-external-methodtables" - # Pkg.add("Revise") + Pkg.add("Revise") Pkg.test("Revise") ' - name: Test while running Revise