Skip to content

Commit ca9241e

Browse files
committed
This fixes JuliaLang#3377. It allows for writing @methods @time 1+1, @functionloc @time 1+1 plus the equivalent for @which, @edit and @less. The macros check for method specialization of the macro and return the dispatched macro.
1 parent 64ca55f commit ca9241e

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

base/interactiveutil.jl

+8-3
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,13 @@ function gen_call_with_extracted_types(fcn, ex0)
254254
Expr(:call, typesof, map(esc, args[2:end])...))
255255
end
256256
exret = Expr(:none)
257+
is_macro = false
257258
ex = expand(ex0)
258-
if !isa(ex, Expr)
259+
if fcn in [:which, :less, :edit, :methods, :functionloc] && ex0.head == :macrocall
260+
# special case @edit @time 1+2 to edit the macro
261+
is_macro = true
262+
exret = Expr(:call, fcn, esc(ex0.args[1]), typesof(ex0.args[2:end]...))
263+
elseif !isa(ex, Expr)
259264
exret = Expr(:call, :error, "expression is not a function call or symbol")
260265
elseif ex.head == :call
261266
if any(e->(isa(e, Expr) && e.head==:(...)), ex0.args) &&
@@ -278,15 +283,15 @@ function gen_call_with_extracted_types(fcn, ex0)
278283
end
279284
end
280285
end
281-
if ex.head == :thunk || exret.head == :none
286+
if (!is_macro && ex.head == :thunk) || exret.head == :none
282287
exret = Expr(:call, :error, "expression is not a function call, "
283288
* "or is too complex for @$fcn to analyze; "
284289
* "break it down to simpler parts if possible")
285290
end
286291
exret
287292
end
288293

289-
for fname in [:which, :less, :edit, :code_typed, :code_warntype,
294+
for fname in [:which, :less, :edit, :methods, :functionloc, :code_typed, :code_warntype,
290295
:code_lowered, :code_llvm, :code_llvm_raw, :code_native]
291296
@eval begin
292297
macro ($fname)(ex0)

test/reflection.jl

+23
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,26 @@ let rts = return_types(TLayout)
237237
@test length(rts) >= 3 # general constructor, specific constructor, and call-to-convert adapter(s)
238238
@test all(rts .== TLayout)
239239
end
240+
241+
module MacroTest
242+
export @macrotest
243+
macro macrotest(x::Int, y::Symbol) end
244+
macro macrotest(x::Int, y::Int)
245+
nothing
246+
end
247+
end
248+
249+
let
250+
using MacroTest
251+
a = 1
252+
m = getfield(current_module(), Symbol("@macrotest"))
253+
@test which(m, Tuple{Int,Symbol})==@which @macrotest 1 a
254+
@test which(m, Tuple{Int,Int})==@which @macrotest 1 1
255+
@test methods(m, Tuple{Int,Symbol})==@methods @macrotest 1 a
256+
@test methods(m, Tuple{Int,Int})==@methods @macrotest 1 1
257+
258+
@test methods(m,Tuple{Int, Int})[1]==@which MacroTest.@macrotest 1 1
259+
@test functionloc(@which @macrotest 1 1)[1] == @functionloc @macrotest 1 1
260+
#Uncomment when #15280 is solved
261+
#@test basename(functionloc(@which @macrotest 1 a)[1]) == "reflection.jl"
262+
end

0 commit comments

Comments
 (0)