Skip to content

Commit 8c5ff78

Browse files
committed
Fix line numbering for Julia 1.5
JuliaLang/julia#35138 changed it so that the method's line number is the declaration, not the first line of the body. This also reworks the line-number detection logic on older releases, and it should be more robust.
1 parent 836d261 commit 8c5ff78

File tree

5 files changed

+75
-35
lines changed

5 files changed

+75
-35
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ julia:
99
- 1.1
1010
- 1.2
1111
- 1.3
12+
- 1.4
1213
- nightly
1314
notifications:
1415
email: false

Project.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Revise"
22
uuid = "295af30f-e4ad-537b-8983-00126c2a3abe"
3-
version = "2.6.0"
3+
version = "2.6.1"
44

55
[deps]
66
CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
@@ -16,7 +16,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
1616
Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
1717

1818
[compat]
19-
CodeTracking = "~0.5.1"
19+
CodeTracking = "0.5.9"
2020
JuliaInterpreter = "~0.7.1"
2121
LoweredCodeUtils = "0.4"
2222
OrderedCollections = "1"

src/Revise.jl

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ using LoweredCodeUtils: next_or_nothing!, isanonymous_typedef, define_anonymous
1414

1515
export revise, includet, entr, MethodSummary
1616

17+
using CodeTracking: line_is_decl
18+
1719
"""
1820
Revise.watching_files[]
1921

src/lowered.jl

+61-30
Original file line numberDiff line numberDiff line change
@@ -156,47 +156,78 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
156156
pc, pc3 = ret
157157
# Get the line number from the body
158158
stmt3 = pc_expr(frame, pc3)
159-
bodycode = stmt3.args[end]
160-
if !isa(bodycode, CodeInfo)
161-
bodycode = @lookup(frame, bodycode)
159+
lnn = nothing
160+
if line_is_decl
161+
sigcode = @lookup(frame, stmt3.args[2])
162+
lnn = sigcode[end]
163+
if !isa(lnn, LineNumberNode)
164+
lnn = nothing
165+
end
162166
end
163-
if isa(bodycode, CodeInfo)
164-
lnn = bodycode.linetable[1]
165-
if lnn.line == 0 && lnn.file == :none && length(bodycode.code) > 1
166-
# This may be a kwarg method. Mimic LoweredCodeUtils.bodymethod,
167-
# except without having a method
168-
stmt = bodycode.code[end-1]
169-
if isa(stmt, Expr) && length(stmt.args) > 1
170-
a = stmt.args[1]
171-
hasself = any(i->LoweredCodeUtils.is_self_call(stmt, bodycode.slotnames, i), 2:length(stmt.args))
172-
if hasself && isa(a, Symbol)
173-
f = getfield(mod, stmt.args[1])
174-
mths = methods(f)
175-
if length(mths) == 1
176-
mth = first(mths)
177-
lnn = LineNumberNode(Int(mth.line), mth.file)
167+
if lnn === nothing
168+
bodycode = stmt3.args[end]
169+
if !isa(bodycode, CodeInfo)
170+
bodycode = @lookup(frame, bodycode)
171+
end
172+
if isa(bodycode, CodeInfo)
173+
lnn = bodycode.linetable[1]
174+
if lnn.line == 0 && lnn.file == :none
175+
lnn = nothing
176+
if length(bodycode.code) > 1
177+
# This may be a kwarg method. Mimic LoweredCodeUtils.bodymethod,
178+
# except without having a method
179+
stmt = bodycode.code[end-1]
180+
if isa(stmt, Expr) && length(stmt.args) > 1
181+
a = stmt.args[1]
182+
hasself = any(i->LoweredCodeUtils.is_self_call(stmt, bodycode.slotnames, i), 2:length(stmt.args))
183+
if isa(a, Core.SlotNumber)
184+
a = bodycode.slotnames[a.id]
185+
end
186+
if hasself && (isa(a, Symbol) || isa(a, GlobalRef))
187+
thismod, thisname = isa(a, Symbol) ? (mod, a) : (a.mod, a.name)
188+
if isdefined(thismod, thisname)
189+
f = getfield(thismod, thisname)
190+
mths = methods(f)
191+
if length(mths) == 1
192+
mth = first(mths)
193+
lnn = LineNumberNode(Int(mth.line), mth.file)
194+
end
195+
end
196+
end
178197
end
179198
end
180-
else
181-
# Just try to find *any* line number
182-
for lnntmp in bodycode.linetable
183-
if lnntmp.line != 0 || lnntmp.file != :none
184-
lnn = lnntmp
185-
break
199+
if lnn === nothing
200+
# Just try to find *any* line number
201+
for lnntmp in bodycode.linetable
202+
if lnntmp.line != 0 || lnntmp.file != :none
203+
lnn = lnntmp
204+
break
205+
end
186206
end
187207
end
188208
end
209+
elseif isexpr(bodycode, :lambda)
210+
lnntmp = bodycode.args[end][1]
211+
if lnntmp.line != 0 || lnntmp.file != :none
212+
lnn = lnntmp
213+
end
189214
end
190-
for sig in signatures
191-
add_signature!(methodinfo, sig, lnn)
215+
end
216+
if lnn === nothing
217+
i = frame.framecode.src.codelocs[pc3]
218+
while i > 0
219+
lnntmp = frame.framecode.src.linetable[i]
220+
if lnntmp.line != 0 || lnntmp.file != :none
221+
lnn = lnntmp
222+
break
223+
end
224+
i -= 1
192225
end
193-
elseif isexpr(bodycode, :lambda)
194-
lnn = bodycode.args[end][1]
226+
end
227+
if lnn !== nothing && (lnn.line != 0 || lnn.file != :none)
195228
for sig in signatures
196229
add_signature!(methodinfo, sig, lnn)
197230
end
198-
else
199-
error("unhandled bodycode ", bodycode)
200231
end
201232
end
202233
elseif stmt.head == :(=) && isa(stmt.args[1], Symbol)

test/runtests.jl

+9-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ using OrderedCollections: OrderedSet
1010
using Test: collect_test_logs
1111
using Base.CoreLogging: Debug,Info
1212

13+
using CodeTracking: line_is_decl
14+
1315
include("common.jl")
1416

1517
throwing_function(bt) = bt[2]
@@ -1263,13 +1265,16 @@ foo(y::Int) = y-51
12631265
triggered(true, false)
12641266
@test false
12651267
catch err
1266-
bt = throwing_function(Revise.update_stacktrace_lineno!(stacktrace(catch_backtrace())))
1268+
st = stacktrace(catch_backtrace())
1269+
Revise.update_stacktrace_lineno!(st)
1270+
bt = throwing_function(st)
12671271
@test bt.file == Symbol(filename) && bt.line == 2
12681272
end
12691273
io = IOBuffer()
12701274
if isdefined(Base, :methodloc_callback)
12711275
print(io, methods(triggered))
1272-
@test occursin(filename * ":2", String(take!(io)))
1276+
mline = line_is_decl ? 1 : 2
1277+
@test occursin(filename * ":$mline", String(take!(io)))
12731278
end
12741279
open(filename, "w") do io
12751280
println(io, """
@@ -1306,7 +1311,8 @@ foo(y::Int) = y-51
13061311
@test occursin(targetstr, String(take!(io)))
13071312
if isdefined(Base, :methodloc_callback)
13081313
print(io, methods(triggered))
1309-
@test occursin(filename * ":3", String(take!(io)))
1314+
mline = line_is_decl ? 2 : 3
1315+
@test occursin(filename * ":$mline", String(take!(io)))
13101316
end
13111317

13121318
push!(to_remove, filename)

0 commit comments

Comments
 (0)