From 5992e9431162285b0871033c4cb282c178791c69 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Fri, 3 Sep 2021 15:31:38 +0900 Subject: [PATCH] add test cases and fixup completion code --- stdlib/REPL/src/REPLCompletions.jl | 21 ++++++++-------- stdlib/REPL/test/replcompletions.jl | 37 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 085c6018e12038..fd63e53f15e032 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -135,9 +135,8 @@ function appendmacro!(syms, macros, needle, endchar) end end -function filtered_mod_names(ffunc::Function, mod::Module, name::AbstractString; - all::Bool=false, imported::Bool=false, usings::Bool=false) - ssyms = names(mod, all = all, imported = imported, usings = usings) +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) @@ -182,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, all=true, imported=true, usings=true)) - else - append!(suggestions, filtered_mod_names(p, mod, name, all=true, usings=true)) + # 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 diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 0a73a944ec8ead..b0a00f914218cb 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -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 + + @assert count(==("foo"), test_complete_context1("f", use)) ≠ 1 + @assert count(==("foo"), test_complete_context1("use.f", M)) ≠ 1 + @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() + + @assert count(==("fuzzyscore"), test_complete_context1("fuzzy", M)) ≠ 1 + @eval M using REPL: fuzzyscore + @test count(==("fuzzyscore"), test_complete_context1("fuzzy", M)) == 1 + + @assert count(==("completions"), test_complete_context1("comp", M)) ≠ 1 + @eval M using REPL.REPLCompletions: completions + @test count(==("completions"), test_complete_context1("comp", M)) == 1 + end + + let # should for `Base` binding + M = Module() + + @assert count(==("@aggressive_constprop"), test_complete_context1("@aggressive_", M)) ≠ 1 + @eval M using Base: @aggressive_constprop + @test count(==("@aggressive_constprop"), test_complete_context1("@aggressive_", M)) == 1 + end +end