Skip to content

Commit

Permalink
Add usings to names in REPL completions. (#42094)
Browse files Browse the repository at this point in the history
Add `usings` to names in REPL completions.

Follow up to #42092, rest of
#36529.

This enables the REPL to use the names imported via `usings` in
completions.

---------

Co-authored-by: Shuhei Kadowaki <[email protected]>
  • Loading branch information
NHDaly and aviatesk authored May 27, 2024
1 parent 23c8bd3 commit eb14cb5
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
22 changes: 11 additions & 11 deletions stdlib/REPL/src/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ function appendmacro!(syms, macros, needle, endchar)
end
end

function filtered_mod_names(ffunc::Function, mod::Module, name::AbstractString, all::Bool = false, imported::Bool = false)
ssyms = names(mod, all = all, imported = imported)
all || filter!(Base.Fix1(Base.isexported, mod), ssyms)
function filtered_mod_names(ffunc::Function, mod::Module, name::AbstractString; kwargs...)
ssyms = names(mod; kwargs...)
# all || filter!(Base.Fix1(Base.isexported, mod), ssyms) # TODO revisit
filter!(ffunc, ssyms)
macros = filter(x -> startswith(String(x), "@" * name), ssyms)
syms = String[sprint((io,s)->Base.show_sym(io, s; allow_macroname=true), s) for s in ssyms if completes_global(String(s), name)]
Expand Down Expand Up @@ -181,14 +181,14 @@ function complete_symbol(@nospecialize(ex), name::String, @nospecialize(ffunc),
end
# Looking for a binding in a module
if mod == context_module
# Also look in modules we got through `using`
mods = ccall(:jl_module_usings, Any, (Any,), context_module)::Vector
for m in mods
append!(suggestions, filtered_mod_names(p, m::Module, name))
end
append!(suggestions, filtered_mod_names(p, mod, name, true, true))
else
append!(suggestions, filtered_mod_names(p, mod, name, true, false))
# special case `Core` and `Base` bindings
# - `Core` bindings should be added to every modules
# - `Base` bindings should be added to non-bare modules
append!(suggestions, filtered_mod_names(p, Core, name))
isdefined(mod, :Base) && append!(suggestions, filtered_mod_names(p, Base, name))
append!(suggestions, filtered_mod_names(p, mod, name; all=true, imported=true, usings=true))
else # dot-accessed module context
append!(suggestions, filtered_mod_names(p, mod, name; all=true, usings=true))
end
elseif val !== nothing # looking for a property of an instance
try
Expand Down
37 changes: 37 additions & 0 deletions stdlib/REPL/test/replcompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2260,3 +2260,40 @@ let s = "Issue53126()."
@test res
@test isempty(c)
end

@testset "complete names from `using`" begin
test_complete_context1(args...; kwargs...) = first(test_complete_context(args...; kwargs...))

let # should work for arbitrary module
M = Module()

use = @eval M module use end
@eval use module def; foo = 42; end

@test count(==("foo"), test_complete_context1("f", use)) == 0
@test count(==("foo"), test_complete_context1("use.f", M)) == 0
@eval use using .def: foo
@test count(==("foo"), test_complete_context1("f", use)) == 1
@test count(==("foo"), test_complete_context1("use.f", M)) == 1 # should work for even dot-accessed module context
end

let # should work for packages
M = Module()

@test count(==("fuzzyscore"), test_complete_context1("fuzzy", M)) == 0
@eval M using REPL: fuzzyscore
@test count(==("fuzzyscore"), test_complete_context1("fuzzy", M)) == 1

@test count(==("completions"), test_complete_context1("comp", M)) == 0
@eval M using REPL.REPLCompletions: completions
@test count(==("completions"), test_complete_context1("comp", M)) == 1
end

let # should for `Base` binding
M = Module()

@test count(==("@assume_effects"), test_complete_context1("@assume_", M)) 1
@eval M using Base: @assume_effects
@test count(==("@assume_effects"), test_complete_context1("@assume_", M)) == 1
end
end

0 comments on commit eb14cb5

Please sign in to comment.