Skip to content

Commit 66b43ab

Browse files
authored
Merge pull request #200 from JunoLab/avi/whereclause
fixes JunoLab/Juno.jl#404
2 parents 438ae46 + 1f9cf9d commit 66b43ab

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

src/outline.jl

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,18 @@ function local_bindings(expr, text, bindings = [], pos = 1, line = 1)
219219
if scope !== nothing
220220
expr.typ == CSTParser.Kw && return bindings
221221

222+
# destructure multiple returns
222223
if ismultiplereturn(expr)
223-
# destructure multiple returns
224-
if expr.args !== nothing
225-
for arg in expr.args
226-
# don't update `pos` & `line`, i.e.: treat all the multiple returns at a same place
227-
local_bindings(arg, text, bindings, pos, line)
228-
end
224+
for arg in expr.args
225+
# don't update `pos` & `line`, i.e.: treat all the multiple returns as same
226+
local_bindings(arg, text, bindings, pos, line)
227+
end
228+
# properly detect the parameters of a method with where clause: https://github.com/JunoLab/Juno.jl/issues/404
229+
elseif iswhereclause(expr)
230+
for arg in expr.args
231+
local_bindings(arg, text, bindings, pos, line)
232+
line += countlines(arg, text, pos)
233+
pos += arg.fullspan
229234
end
230235
else
231236
# find local binds in a scope
@@ -320,22 +325,26 @@ end
320325

321326
function scopeof(expr::CSTParser.EXPR)
322327
scope = CSTParser.scopeof(expr)
323-
if scope nothing
328+
if scope !== nothing
324329
return scope
325330
else
326331
# can remove this with CSTParser 0.6.3
327332
if expr.typ == CSTParser.BinaryOpCall && expr.args[2].kind == CSTParser.Tokens.ANON_FUNC
328333
return :anon
329334
end
330335

331-
if expr.typ == CSTParser.Call && expr.parent nothing && scopeof(expr.parent) == nothing
336+
if expr.typ == CSTParser.Call && expr.parent !== nothing && scopeof(expr.parent) == nothing
332337
return :call
333338
end
334339

335-
if expr.typ == CSTParser.TupleH && expr.parent nothing && scopeof(expr.parent) == nothing
340+
if expr.typ == CSTParser.TupleH && expr.parent !== nothing && scopeof(expr.parent) == nothing
336341
return :tupleh
337342
end
338343

344+
if iswhereclause(expr)
345+
return :where
346+
end
347+
339348
if expr.typ == CSTParser.MacroCall
340349
return :macro
341350
end
@@ -357,9 +366,15 @@ end
357366

358367
function ismultiplereturn(expr::CSTParser.EXPR)
359368
expr.typ === CSTParser.TupleH &&
360-
!isempty(filter(a -> CSTParser.bindingof(a) !== nothing, expr.args))
369+
expr.args !== nothing &&
370+
!isempty(filter(a -> CSTParser.bindingof(a) !== nothing, expr.args))
361371
end
362372

373+
function iswhereclause(expr::CSTParser.EXPR)
374+
expr.typ === CSTParser.WhereOpCall &&
375+
expr.parent !== nothing &&
376+
expr.args !== nothing
377+
end
363378

364379
"""
365380
str_value(x::CSTParser.EXPR)

test/outline.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,24 @@
131131
end
132132
end
133133

134+
# detect all the method parameters of a method with a `where` clause
135+
let str = """
136+
function push!′(ary::Vector{T}, item::S) where {T, S<:T}
137+
tmpvec, tmpitem = ary, item
138+
push!(tmpvec, tmpitem)
139+
end
140+
"""
141+
142+
binds = map(l -> l[:name], Atom.locals(str, 1, 0))
143+
@test "ary" in binds
144+
@test "item" in binds
145+
@test "T" in binds
146+
@test "S" in binds
147+
@test "tmpvec" in binds
148+
@test "tmpitem" in binds
149+
@test "push!′" in binds
150+
end
151+
134152
let str = """
135153
function foo(x)
136154
@macrocall begin

0 commit comments

Comments
 (0)