diff --git a/src/datatip.jl b/src/datatip.jl
index 1c2a62ed..8f7db288 100644
--- a/src/datatip.jl
+++ b/src/datatip.jl
@@ -1,7 +1,6 @@
#=
-@TODO:
-Use our own UI components for this: atom-ide-ui is already deprecated, ugly, not fully functional, and and...
-Once we can come to handle links within datatips, we may want to append method tables as well
+@TODO use our own UI components for this:
+atom-ide-ui is already deprecated, ugly, not fully functional, and and...
=#
handle("datatip") do data
@@ -25,7 +24,7 @@ function datatip(word, mod, path, column = 1, row = 1, startrow = 0, context = "
ldt = localdatatip(word, column, row, startrow, context)
isempty(ldt) || return datatip(ldt)
- tdt = topleveldatatip(mod, word)
+ tdt = globaldatatip(mod, word)
tdt !== nothing && return Dict(:error => false, :strings => tdt)
return Dict(:error => true) # nothing hits
@@ -36,7 +35,7 @@ datatip(dt::Int) = Dict(:error => false, :line => dt)
datatip(dt::Vector{Int}) = datatip(dt[1])
function localdatatip(word, column, row, startrow, context)
- word = first(split(word, '.')) # ignore dot accessors
+ word = first(split(word, '.')) # always ignore dot accessors
position = row - startrow
ls = locals(context, position, column)
filter!(ls) do l
@@ -56,7 +55,7 @@ function localdatatip(l, word, startrow)
end
end
-function topleveldatatip(mod, word)
+function globaldatatip(mod, word)
docs = @errs getdocs(mod, word)
docs isa EvalError && return nothing
@@ -71,6 +70,9 @@ function topleveldatatip(mod, word)
processdoc!(docs, docstr, datatip)
+ ml = methods(val)
+ processmethods!(ml, datatip)
+
return datatip
end
@@ -122,6 +124,20 @@ processval!(val::Function, docstr, datatip) = begin
end
processval!(::Undefined, docstr, datatip) = nothing
+function processmethods!(ml, datatip)
+ ms = collect(ml)
+ isempty(ms) && return
+
+ substr = s"\g
in \g
at \g"
+ msstr = map(ms) do m
+ s = replace(string(m), methodloc_regex => substr)
+ "$s"
+ end |> join
+
+ name = ms[1].name
+ pushmarkdown!(datatip, "$name
has **$(length(ms))** methods:
")
+end
+
function pushmarkdown!(datatip, markdown)
(markdown == "" || markdown == "\n") && return
push!(datatip, Dict(:type => :markdown, :value => markdown))
diff --git a/src/display/methods.jl b/src/display/methods.jl
index 12008d8a..ddb210ef 100644
--- a/src/display/methods.jl
+++ b/src/display/methods.jl
@@ -4,9 +4,11 @@ stripparams(t) = replace(t, r"\{([A-Za-z, ]*?)\}" => "")
interpose(xs, y) = map(i -> iseven(i) ? xs[i÷2] : y, 2:2length(xs))
+const methodloc_regex = r"(?.+) in (?.+) at (?.+)$"
+
function view(m::Method)
str = sprint(show, "text/html", m)
- str = replace(str, r" in .* at .*$" => "")
+ str = replace(str, methodloc_regex => s"\g")
str = string("", str, "")
tv, decls, file, line = Base.arg_decl_parts(m)
HTML(str), file == :null ? "not found" : Atom.baselink(string(file), line)
diff --git a/src/goto.jl b/src/goto.jl
index 8e8ea0dd..d360c0d0 100644
--- a/src/goto.jl
+++ b/src/goto.jl
@@ -32,7 +32,7 @@ function gotosymbol(
localitems = localgotoitem(word, path, column, row, startrow, context)
isempty(localitems) || return Dict(
:error => false,
- :items => map(Dict, localitems),
+ :items => map(Dict, localitems)
)
end
@@ -66,7 +66,7 @@ Dict(gotoitem::GotoItem) = Dict(
### local goto
function localgotoitem(word, path, column, row, startrow, context)
- word = first(split(word, '.')) # ignore dot accessors
+ word = first(split(word, '.')) # always ignore dot accessors
position = row - startrow
ls = locals(context, position, column)
filter!(ls) do l
@@ -86,31 +86,31 @@ localgotoitem(word, ::Nothing, column, row, startrow, context) = [] # when `path
function globalgotoitems(word, mod, text, path)
mod = getmodule(mod)
- moduleitems = modulegotoitems(word, mod)
- isempty(moduleitems) || return moduleitems
+ # strip a dot-accessed module if exists
+ identifiers = split(word, '.')
+ head = string(identifiers[1])
+ if head ≠ word && getfield′(mod, head) isa Module
+ # if `head` is a module, update `word` and `mod`
+ nextword = join(identifiers[2:end], '.')
+ return globalgotoitems(nextword, head, text, path)
+ end
+
+ val = getfield′(mod, word)
+ val isa Module && return [GotoItem(val)] # module goto
toplevelitems = toplevelgotoitems(word, mod, text, path)
- # only append methods that are not caught by `toplevelgotoitems`
+ # append method gotos that are not caught by `toplevelgotoitems`
+ ml = methods(val)
files = map(item -> item.file, toplevelitems)
- methoditems = filter!(item -> item.file ∉ files, methodgotoitems(mod, word))
-
+ methoditems = filter!(item -> item.file ∉ files, methodgotoitems(ml))
append!(toplevelitems, methoditems)
end
## module goto
-function modulegotoitems(word, mod)::Vector{GotoItem}
- mod = getfield′(mod, Symbol(word))
- return mod isa Module ? [GotoItem(mod)] : []
-end
-
function GotoItem(mod::Module)
- file, line = if mod == Main
- MAIN_MODULE_LOCATION[]
- else
- moduledefinition(mod)
- end
+ file, line = mod == Main ? MAIN_MODULE_LOCATION[] : moduledefinition(mod)
GotoItem(string(mod), file, line - 1)
end
@@ -120,16 +120,6 @@ const PathItemsMaps = Dict{String, Vector{ToplevelItem}}
const SYMBOLSCACHE = Dict{String, PathItemsMaps}()
function toplevelgotoitems(word, mod, text, path)
- # strip a dot-accessed module if exists
- identifiers = split(word, '.')
- head = identifiers[1]
- if head ≠ word && (val = getfield′(mod, string(head))) isa Module
- # if `head` is a module, update `word` and `mod`
- nextword = join(identifiers[2:end], '.')
- nextmod = val
- return toplevelgotoitems(nextword, nextmod, text, path)
- end
-
key = string(mod)
pathitemsmaps = if haskey(SYMBOLSCACHE, key)
SYMBOLSCACHE[key]
@@ -139,8 +129,8 @@ function toplevelgotoitems(word, mod, text, path)
ismacro(word) && (word = lstrip(word, '@'))
ret = Vector{GotoItem}()
- for (path, items) ∈ pathitemsmaps
- for item ∈ filter(item -> filtertoplevelitem(word, item), items)
+ for (path, items) in pathitemsmaps
+ for item in filter(item -> filtertoplevelitem(word, item), items)
push!(ret, GotoItem(path, item))
end
end
@@ -169,7 +159,7 @@ end
function _searchtoplevelitems(mod::Module, pathitemsmaps::PathItemsMaps)
entrypath, paths = modulefiles(mod) # Revise-like approach
if entrypath !== nothing
- for p ∈ [entrypath; paths]
+ for p in [entrypath; paths]
_searchtoplevelitems(p, pathitemsmaps)
end
else # if Revise-like approach fails, fallback to CSTParser-based approach
@@ -188,14 +178,13 @@ function _searchtoplevelitems(path::String, pathitemsmaps::PathItemsMaps)
push!(pathitemsmaps, pathitemsmap)
end
-# module-walk by CSTParser-based, looking for toplevel `installed` calls
+# module-walk based on CSTParser, looking for toplevel `installed` calls
function _searchtoplevelitems(text::String, path::String, pathitemsmaps::PathItemsMaps)
parsed = CSTParser.parse(text, true)
items = toplevelitems(parsed, text)
- pathitemsmap = path => items
- push!(pathitemsmaps, pathitemsmap)
+ push!(pathitemsmaps, path => items)
- # looking for toplevel `installed` calls
+ # looking for toplevel `include` calls
for item in items
if item isa ToplevelCall
expr = item.expr
@@ -278,7 +267,7 @@ function regeneratesymbols()
unloadedlen = length(unloaded)
total = loadedlen + unloadedlen
- for (i, mod) ∈ enumerate(Base.loaded_modules_array())
+ for (i, mod) in enumerate(Base.loaded_modules_array())
try
modstr = string(mod)
modstr == "__PackagePrecompilationStatementModule" && continue # will cause error
@@ -292,7 +281,7 @@ function regeneratesymbols()
end
end
- for (i, pkg) ∈ enumerate(unloaded)
+ for (i, pkg) in enumerate(unloaded)
try
path = Base.find_package(pkg)
text = read(path, String)
@@ -311,27 +300,19 @@ end
## method goto
-function methodgotoitems(mod, word)::Vector{GotoItem}
- ms = @errs getmethods(mod, word)
- if ms isa EvalError
- []
- else
- map(GotoItem, aggregatemethods(ms))
- end
-end
+methodgotoitems(ml) = map(GotoItem, aggregatemethods(ml))
# aggregate methods with default arguments to the ones with full arguments
-aggregatemethods(f) = aggregatemethods(methods(f))
-aggregatemethods(ms::MethodList) = aggregatemethods(collect(ms))
-function aggregatemethods(ms::Vector{Method})
- ms = sort(ms, by = m -> m.nargs, rev = true)
+function aggregatemethods(ml)
+ ms = collect(ml)
+ sort!(ms, by = m -> m.nargs, rev = true)
unique(m -> (m.file, m.line), ms)
end
function GotoItem(m::Method)
_, link = view(m)
sig = sprint(show, m)
- text = replace(sig, r" in .* at .*$" => "")
+ text = replace(sig, methodloc_regex => s"\g")
file = link.file
line = link.line - 1
secondary = join(link.contents)
diff --git a/src/utils.jl b/src/utils.jl
index 3f3e631e..59868fa0 100644
--- a/src/utils.jl
+++ b/src/utils.jl
@@ -111,6 +111,15 @@ end
# string utilties
# ---------------
+"""
+ strlimit(str::AbstractString, limit::Int = 30, ellipsis::AbstractString = "…")
+
+Chops off `str` so that its _length_ doesn't exceed `limit`. The excessive part
+ will be replaced by `ellipsis`.
+
+!!! note
+ The length of returned string will _never_ exceed `limit`.
+"""
function strlimit(str::AbstractString, limit::Int = 30, ellipsis::AbstractString = "…")
will_append = length(str) > limit
@@ -130,7 +139,11 @@ end
shortstr(val) = strlimit(string(val), 20)
-# singleton type for undefined values
+"""
+ Undefined
+
+singleton type representing undefined values
+"""
struct Undefined end
# get utilities
diff --git a/test/datatip.jl b/test/datatip.jl
index 90258a9d..f00c6359 100644
--- a/test/datatip.jl
+++ b/test/datatip.jl
@@ -19,7 +19,7 @@
@test localdatatip("l", 4) == 3 # line
end
- # remove dot accessors
+ # ignore dot accessors
let str = """
function withdots(expr::CSTParser.EXPR)
bind = CSTParser.bindingof(expr.args[1])
@@ -68,8 +68,8 @@
end
end
- @testset "toplevel datatips" begin
- using Atom: topleveldatatip
+ @testset "global datatips" begin
+ using Atom: globaldatatip
## method datatip
@eval Main begin
@@ -81,7 +81,7 @@
datatipmethodtest() = nothing
end
- let datatip = topleveldatatip("Main", "datatipmethodtest")
+ let datatip = globaldatatip("Main", "datatipmethodtest")
@test datatip isa Vector
firsttip = datatip[1]
secondtip = datatip[2]
@@ -94,7 +94,7 @@
## variable datatip
@eval Main datatipvariabletest = "this string should be shown in datatip"
- let datatip = topleveldatatip("Main", "datatipvariabletest")
+ let datatip = globaldatatip("Main", "datatipvariabletest")
@test datatip isa Vector
firsttip = datatip[1]
@test firsttip[:type] == :snippet
diff --git a/test/goto.jl b/test/goto.jl
index f68ad548..129483ec 100644
--- a/test/goto.jl
+++ b/test/goto.jl
@@ -1,8 +1,4 @@
@testset "goto symbols" begin
- using Atom: modulegotoitems, toplevelgotoitems, SYMBOLSCACHE,
- regeneratesymbols, methodgotoitems, globalgotoitems
- using CSTParser
-
@testset "goto local symbols" begin
let str = """
function localgotoitem(word, path, column, row, startRow, context) # L0
@@ -31,7 +27,7 @@
@test localgotoitem("l", 8)[:line] === 7
end
- # remove dot accessors
+ # ignore dot accessors
let str = """
function withdots(expr::CSTParser.EXPR)
bind = CSTParser.bindingof(expr.args[1])
@@ -49,204 +45,199 @@
@test Atom.localgotoitem("word", nothing, 1, 1, 0, "") == []
end
- @testset "module goto" begin
- let item = modulegotoitems("Atom", Main)[1]
- @test item.file == joinpath′(atomjldir, "Atom.jl")
- @test item.line == 3
- end
- let item = modulegotoitems("Junk2", Main.Junk)[1]
- @test item.file == joinpath′(junkpath)
- @test item.line == 14
- end
- end
+ @testset "goto global symbols" begin
+ using Atom: globalgotoitems, toplevelgotoitems, SYMBOLSCACHE,
+ regeneratesymbols, methodgotoitems
- @testset "goto toplevel symbols" begin
- ## where Revise approach works, i.e.: precompiled modules
- let path = joinpath′(atomjldir, "comm.jl")
+ ## strip a dot-accessed modules
+ let
+ path = joinpath′(@__DIR__, "..", "src", "comm.jl")
text = read(path, String)
- mod = Atom
- key = "Atom"
- word = "handlers"
-
- # basic
- let items = toplevelgotoitems(word, mod, text, path) .|> Dict
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:text] == word
- end
-
- # check caching works
- @test haskey(SYMBOLSCACHE, key)
+ items = Dict.(globalgotoitems("Atom.handlers", "Atom", text, path))
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == "handlers"
+ items = Dict.(globalgotoitems("Main.Atom.handlers", "Atom", text, path))
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == "handlers"
- # check the Revise-like approach finds all files in Atom module
- @test length(SYMBOLSCACHE[key]) == length(atommodfiles)
+ # can access the non-exported (non-method) bindings in the other module
+ path = joinpath′(@__DIR__, "..", "src", "goto.jl")
+ text = read(@__FILE__, String)
+ items = Dict.(globalgotoitems("Atom.SYMBOLSCACHE", "Main", text, @__FILE__))
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == "SYMBOLSCACHE"
+ end
- # when `path` isn't given, i.e. via docpane / workspace
- let items = toplevelgotoitems(word, mod, "", nothing) .|> Dict
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:text] == word
+ @testset "goto modules" begin
+ let item = globalgotoitems("Atom", "Main", "", nothing)[1]
+ @test item.file == joinpath′(atomjldir, "Atom.jl")
+ @test item.line == 3
end
-
- # same as above, but without any previous cache -- falls back to CSTPraser-based module-walk
- delete!(SYMBOLSCACHE, key)
-
- let items = toplevelgotoitems(word, mod, "", nothing) .|> Dict
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:text] == word
+ let item = globalgotoitems("Junk2", "Main.Junk", "", nothing)[1]
+ @test item.file == joinpath′(junkpath)
+ @test item.line == 14
end
-
- # check CSTPraser-based module-walk finds all the included files
- # currently broken:
- # - files in submodules are included
- # - webio.jl is excluded since `include("webio.jl")` is a toplevel call
- @test_broken length(SYMBOLSCACHE[key]) == length(atommoddir)
end
- ## where the Revise-like approach doesn't work, e.g. non-precompiled modules
- let path = junkpath
- text = read(path, String)
- mod = Main.Junk
- key = "Main.Junk"
- word = "toplevelval"
-
- # basic
- let items = toplevelgotoitems(word, mod, text, path) .|> Dict
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:line] == 16
- @test items[1][:text] == word
+ @testset "goto toplevel symbols" begin
+ ## where Revise approach works, i.e.: precompiled modules
+ let path = joinpath′(atomjldir, "comm.jl")
+ text = read(path, String)
+ mod = Atom
+ key = "Atom"
+ word = "handlers"
+
+ # basic
+ let items = toplevelgotoitems(word, mod, text, path) .|> Dict
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == word
+ end
+
+ # check caching works
+ @test haskey(SYMBOLSCACHE, key)
+
+ # check the Revise-like approach finds all files in Atom module
+ @test length(SYMBOLSCACHE[key]) == length(atommodfiles)
+
+ # when `path` isn't given, i.e. via docpane / workspace
+ let items = toplevelgotoitems(word, mod, "", nothing) .|> Dict
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == word
+ end
+
+ # same as above, but without any previous cache -- falls back to CSTPraser-based module-walk
+ delete!(SYMBOLSCACHE, key)
+
+ let items = toplevelgotoitems(word, mod, "", nothing) .|> Dict
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == word
+ end
+
+ # check CSTPraser-based module-walk finds all the included files
+ # currently broken:
+ # - files in submodules are included
+ # - webio.jl is excluded since `include("webio.jl")` is a toplevel call
+ @test_broken length(SYMBOLSCACHE[key]) == length(atommoddir)
end
- # check caching works
- @test haskey(Atom.SYMBOLSCACHE, key)
-
- # when `path` isn't given, i.e.: via docpane / workspace
- let items = toplevelgotoitems(word, mod, "", nothing) .|> Dict
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:line] == 16
- @test items[1][:text] == word
+ ## where the Revise-like approach doesn't work, e.g. non-precompiled modules
+ let path = junkpath
+ text = read(path, String)
+ mod = Main.Junk
+ key = "Main.Junk"
+ word = "toplevelval"
+
+ # basic
+ let items = toplevelgotoitems(word, mod, text, path) .|> Dict
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:line] == 16
+ @test items[1][:text] == word
+ end
+
+ # check caching works
+ @test haskey(Atom.SYMBOLSCACHE, key)
+
+ # when `path` isn't given, i.e.: via docpane / workspace
+ let items = toplevelgotoitems(word, mod, "", nothing) .|> Dict
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:line] == 16
+ @test items[1][:text] == word
+ end
end
end
- # handle dot accessors gracefully
- let
- # can access the non-exported (non-method) bindings in the other module
- path = joinpath′(@__DIR__, "..", "src", "goto.jl")
- text = read(@__FILE__, String)
- items = Dict.(toplevelgotoitems("Atom.SYMBOLSCACHE", Main, text, @__FILE__))
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:text] == "SYMBOLSCACHE"
-
- # handle if a module is duplicated
- path = joinpath′(@__DIR__, "..", "src", "comm.jl")
+ @testset "updating toplevel symbols" begin
+ mod = "Main.Junk"
+ path = junkpath
text = read(path, String)
- items = Dict.(toplevelgotoitems("Atom.handlers", Atom, text, path))
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:text] == "handlers"
- end
+ function updatesymbols(mod, text, path)
+ parsed = CSTParser.parse(text, true)
+ items = Atom.toplevelitems(parsed, text)
+ Atom.updatesymbols(text, mod, path, items)
+ end
- # don't error on the fallback case
- @test toplevelgotoitems("word", Main, "", nothing) == []
- end
+ # check there is no cache before updating
+ @test filter(SYMBOLSCACHE[mod][path]) do item
+ Atom.str_value(item.expr) == "toplevelval2"
+ end |> isempty
- @testset "updating toplevel symbols" begin
- mod = "Main.Junk"
- path = junkpath
- text = read(path, String)
- function updatesymbols(mod, text, path)
- parsed = CSTParser.parse(text, true)
- items = Atom.toplevelitems(parsed, text)
- Atom.updatesymbols(text, mod, path, items)
- end
+ # mock updatesymbol handler
+ originallines = readlines(path)
+ newtext = join(originallines[1:end - 1], '\n')
+ word = "toplevelval2"
+ newtext *= "\n$word = :youshoulderaseme\nend"
+ updatesymbols(mod, newtext, path)
- # check there is no cache before updating
- @test filter(SYMBOLSCACHE[mod][path]) do item
- Atom.str_value(item.expr) == "toplevelval2"
- end |> isempty
+ # check the cache is updated
+ @test filter(SYMBOLSCACHE[mod][path]) do item
+ Atom.str_value(item.expr) == word
+ end |> !isempty
- # mock updatesymbol handler
- originallines = readlines(path)
- newtext = join(originallines[1:end - 1], '\n')
- word = "toplevelval2"
- newtext *= "\n$word = :youshoulderaseme\nend"
- updatesymbols(mod, newtext, path)
-
- # check the cache is updated
- @test filter(SYMBOLSCACHE[mod][path]) do item
- Atom.str_value(item.expr) == word
- end |> !isempty
+ let items = toplevelgotoitems(word, mod, newtext, path) .|> Dict
+ @test !isempty(items)
+ @test items[1][:file] == path
+ @test items[1][:text] == "toplevelval2"
+ end
- let items = toplevelgotoitems(word, mod, newtext, path) .|> Dict
- @test !isempty(items)
- @test items[1][:file] == path
- @test items[1][:text] == "toplevelval2"
+ # re-update the cache
+ updatesymbols(mod, text, path)
+ @test filter(SYMBOLSCACHE[mod][path]) do item
+ Atom.str_value(item.expr) == word
+ end |> isempty
end
- # re-update the cache
- updatesymbols(mod, text, path)
- @test filter(SYMBOLSCACHE[mod][path]) do item
- Atom.str_value(item.expr) == word
- end |> isempty
- end
-
- @testset "regenerating symbols" begin
- # @info "––– caching symbols in loaded modules (only errors shown) ------"
- # with_logger(ConsoleLogger(stderr, Base.CoreLogging.Warn)) do
- regeneratesymbols()
- # end
- # @info "––– finished caching -------------------------------------------"
-
- @test haskey(SYMBOLSCACHE, "Base")
- @test length(keys(SYMBOLSCACHE["Base"])) > 100
- @test haskey(SYMBOLSCACHE, "Example") # cache symbols even if not loaded
- @test toplevelgotoitems("hello", "Example", "", nothing) |> !isempty
- end
+ @testset "regenerating symbols" begin
+ regeneratesymbols()
- @testset "goto methods" begin
- ## basic
- # `Atom.handlemsg` is not defined with default args
- let items = methodgotoitems("Main", "Atom.handlemsg")
- @test length(items) === length(methods(Atom.handlemsg))
+ @test haskey(SYMBOLSCACHE, "Base")
+ @test length(keys(SYMBOLSCACHE["Base"])) > 100
+ @test haskey(SYMBOLSCACHE, "Example") # cache symbols even if not loaded
+ @test toplevelgotoitems("hello", "Example", "", nothing) |> !isempty
end
- ## module awareness
- let items = methodgotoitems("Atom", "handlemsg")
- @test length(items) === length(methods(Atom.handlemsg))
- end
+ @testset "goto methods" begin
+ ## basic
+ let ms = methods(Atom.handlemsg)
+ @test length(methodgotoitems(ms)) === length(ms)
+ end
- ## aggregate methods with default params
- @eval Main function funcwithdefaultargs(args, defarg = "default") end
+ ## aggregate methods with default params
+ @eval Main function funcwithdefaultargs(args, defarg = "default") end
- let items = methodgotoitems("Main", "funcwithdefaultargs") .|> Dict
- # should be handled as an unique method
- @test length(items) === 1
- # show a method with full arguments
- @test "funcwithdefaultargs(args, defarg)" ∈ map(i -> i[:text], items)
- end
+ let items = methodgotoitems(methods(funcwithdefaultargs)) .|> Dict
+ # should be handled as an unique method
+ @test length(items) === 1
+ # show a method with full arguments
+ @test "funcwithdefaultargs(args, defarg)" in map(i -> i[:text], items)
+ end
- @eval Main function funcwithdefaultargs(args::String, defarg = "default") end
+ @eval Main function funcwithdefaultargs(args::String, defarg = "default") end
- let items = methodgotoitems("Main", "funcwithdefaultargs") .|> Dict
- # should be handled as different methods
- @test length(items) === 2
- # show methods with full arguments
- @test "funcwithdefaultargs(args, defarg)" ∈ map(i -> i[:text], items)
- @test "funcwithdefaultargs(args::String, defarg)" ∈ map(i -> i[:text], items)
+ let items = methodgotoitems(methods(funcwithdefaultargs)) .|> Dict
+ # should be handled as different methods
+ @test length(items) === 2
+ # show methods with full arguments
+ @test "funcwithdefaultargs(args, defarg)" in map(i -> i[:text], items)
+ @test "funcwithdefaultargs(args::String, defarg)" in map(i -> i[:text], items)
+ end
end
- end
- @testset "goto global symbols" begin # toplevel symbol goto & method goto
- # both the original methods and the toplevel bindings that are overloaded
- # in a context module should be shown
+ ## both the original methods and the toplevel bindings that are overloaded in a context module should be shown
let items = globalgotoitems("isconst", "Main.Junk", "", nothing)
@test length(items) === 2
- @test "isconst(m::Module, s::Symbol)" ∈ map(item -> item.text, items) # from Base
- @test "Base.isconst(::JunkType)" ∈ map(item -> item.text, items) # from Junk
+ @test "isconst(m::Module, s::Symbol)" in map(item -> item.text, items) # from Base
+ @test "Base.isconst(::JunkType)" in map(item -> item.text, items) # from Junk
end
+
+ ## don't error on the fallback case
+ @test globalgotoitems("word", "Main", "", nothing) == []
end
end