Skip to content

Commit

Permalink
Merge pull request #17488 from JuliaLang/jn/reflect-all
Browse files Browse the repository at this point in the history
ensure reflection returns all names in a module
  • Loading branch information
vtjnash authored Jul 20, 2016
2 parents ee5e231 + 11313a6 commit d3a8988
Show file tree
Hide file tree
Showing 15 changed files with 288 additions and 189 deletions.
2 changes: 1 addition & 1 deletion base/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function complete_symbol(sym, ffunc)
# We will exclude the results that the user does not want, as well
# as excluding Main.Main.Main, etc., because that's most likely not what
# the user wants
p = s->(ffunc(mod, s) && s != module_name(mod))
p = s->(!Base.isdeprecated(mod, s) && s != module_name(mod) && ffunc(mod, s))
# Looking for a binding in a module
if mod == context_module
# Also look in modules we got through `using`
Expand Down
2 changes: 1 addition & 1 deletion base/docs/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ moduleusings(mod) = ccall(:jl_module_usings, Any, (Any,), mod)
filtervalid(names) = filter(x->!ismatch(r"#", x), map(string, names))

accessible(mod::Module) =
[names(mod, true, true);
[filter!(s->Base.isdeprecated(mod, s), names(mod, true, true));
map(names, moduleusings(mod))...;
builtins] |> unique |> filtervalid

Expand Down
2 changes: 1 addition & 1 deletion base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ function summarysize(obj::Module, seen, excl)
haskey(seen, obj) ? (return 0) : (seen[obj] = true)
size::Int = Core.sizeof(obj)
for binding in names(obj, true)
if isdefined(obj, binding)
if isdefined(obj, binding) && !isdeprecated(obj, binding)
value = getfield(obj, binding)
if !isa(value, Module) || module_parent(value) === obj
size += summarysize(value, seen, excl)::Int
Expand Down
18 changes: 7 additions & 11 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,11 @@ function fullname(m::Module)
return tuple(fullname(mp)..., mn)
end

names(m::Module, all::Bool, imported::Bool) = sort!(ccall(:jl_module_names, Array{Symbol,1}, (Any,Int32,Int32), m, all, imported))
names(m::Module, all::Bool) = names(m, all, false)
names(m::Module) = names(m, false, false)
names(m::Module, all::Bool=false, imported::Bool=false) = sort!(ccall(:jl_module_names, Array{Symbol,1}, (Any,Int32,Int32), m, all, imported))

isexported(m::Module, s::Symbol) = ccall(:jl_module_exports_p, Cint, (Any, Any), m, s)!=0

function isbindingresolved(m::Module, var::Symbol)
ccall(:jl_binding_resolved_p, Cint, (Any, Any), m, var) != 0
end
isexported(m::Module, s::Symbol) = ccall(:jl_module_exports_p, Cint, (Any, Any), m, s) != 0
isdeprecated(m::Module, s::Symbol) = ccall(:jl_is_binding_deprecated, Cint, (Any, Any), m, s) != 0
isbindingresolved(m::Module, var::Symbol) = ccall(:jl_binding_resolved_p, Cint, (Any, Any), m, var) != 0

binding_module(s::Symbol) = binding_module(current_module(), s)
function binding_module(m::Module, s::Symbol)
Expand Down Expand Up @@ -158,8 +154,8 @@ function instances end
# subtypes
function _subtypes(m::Module, x::DataType, sts=Set(), visited=Set())
push!(visited, m)
for s in names(m,true)
if isdefined(m,s)
for s in names(m, true)
if isdefined(m, s) && !isdeprecated(m, s)
t = getfield(m, s)
if isa(t, DataType) && t.name.name == s && supertype(t).name == x.name
ti = typeintersect(t, x)
Expand All @@ -169,7 +165,7 @@ function _subtypes(m::Module, x::DataType, sts=Set(), visited=Set())
end
end
end
sts
return sts
end
subtypes(m::Module, x::DataType) = sort(collect(_subtypes(m, x)), by=string)
subtypes(x::DataType) = subtypes(Main, x)
Expand Down
103 changes: 46 additions & 57 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1072,7 +1072,6 @@ function dump(io::IO, x::SimpleVector, n::Int, indent)
end
end
end
isempty(indent) && println(io)
nothing
end

Expand All @@ -1098,11 +1097,13 @@ function dump(io::IO, x::ANY, n::Int, indent)
else
!isa(x,Function) && print(io, " ", x)
end
isempty(indent) && println(io)
nothing
end

dump(io::IO, x::Module, n::Int, indent) = print(io, "Module ", x)
dump(io::IO, x::String, n::Int, indent) = (print(io, "String "); show(io, x))
dump(io::IO, x::Symbol, n::Int, indent) = print(io, typeof(x), " ", x)
dump(io::IO, x::Union, n::Int, indent) = print(io, x)

function dump_elts(io::IO, x::Array, n::Int, indent, i0, i1)
for i in i0:i1
Expand Down Expand Up @@ -1136,93 +1137,81 @@ function dump(io::IO, x::Array, n::Int, indent)
end
end
end
isempty(indent) && println(io)
nothing
end
function dump(io::IO, x::Symbol, n::Int, indent)
print(io, typeof(x), " ", x)
isempty(indent) && println(io)
nothing
end

# Types
function dump(io::IO, x::Union, n::Int, indent)
print(io, x)
isempty(indent) && println(io)
nothing
end

function dump(io::IO, x::DataType, n::Int, indent)
print(io, x)
if x !== Any
print(io, " <: ", supertype(x))
end
if !(x <: Tuple)
tvar_io = IOContext(io, :tvar_env => Any[x.parameters...])
fields = fieldnames(x)
if n > 0
for idx in 1:length(fields)
println(io)
print(io, indent, " ", fields[idx], "::")
print(io, fieldtype(x,idx))
print(tvar_io, fieldtype(x, idx))
end
end
end
isempty(indent) && println(io)
nothing
end

# dumptype is for displaying abstract type hierarchies like Jameson
# Nash's wiki page: https://github.com/JuliaLang/julia/wiki/Types-Hierarchy

# dumptype is for displaying abstract type hierarchies,
# based on Jameson Nash's examples/typetree.jl
function dumptype(io::IO, x::ANY, n::Int, indent)
# based on Jameson Nash's examples/typetree.jl
println(io, x)
if n == 0 # too deeply nested
return
end
typargs(t) = split(string(t), "{")[1]
# todo: include current module?
for m in (Core, Base)
for s in fieldnames(m)
if isdefined(m,s)
t = eval(m,s)
if isa(t, TypeConstructor)
if string(x.name) == typargs(t) ||
("Union" == split(string(t), "(")[1] &&
any(map(tt -> string(x.name) == typargs(tt), t.body.types)))
targs = join(t.parameters, ",")
println(io, indent, " ", s,
!isempty(t.parameters) ? "{$targs}" : "",
" = ", t)
end
elseif isa(t, Union)
if any(tt -> string(x.name) == typargs(tt), t.types)
println(io, indent, " ", s, " = ", t)
end
elseif isa(t, DataType) && supertype(t).name == x.name
# type aliases
if string(s) != string(t.name)
println(io, indent, " ", s, " = ", t.name)
elseif t != Any
print(io, indent, " ")
dump(io, t, n - 1, string(indent, " "))
end
print(io, x)
n == 0 && return # too deeply nested
isa(x, DataType) && x.abstract && dumpsubtypes(io, x, Main, n, indent)
nothing
end

directsubtype(a::DataType, b::DataType) = supertype(a).name === b.name
directsubtype(a::TypeConstructor, b::DataType) = directsubtype(a.body, b)
directsubtype(a::Union, b::DataType) = any(t->directsubtype(t, b), a.types)
function dumpsubtypes(io::IO, x::DataType, m::Module, n::Int, indent)
for s in names(m, true)
if isdefined(m, s) && !isdeprecated(m, s)
t = getfield(m, s)
if t === x || t === m
continue
elseif isa(t, Module) && module_name(t) === s && module_parent(t) === m
# recurse into primary module bindings
dumpsubtypes(io, x, t, n, indent)
elseif isa(t, TypeConstructor) && directsubtype(t, x)
println(io)
print(io, indent, " ", m, ".", s)
isempty(t.parameters) || print(io, "{", join(t.parameters, ","), "}")
print(io, " = ", t)
elseif isa(t, Union) && directsubtype(t, x)
println(io)
print(io, indent, " ", m, ".", s, " = ", t)
elseif isa(t, DataType) && directsubtype(t, x)
println(io)
if t.name.module !== m || t.name.name != s
# aliases to types
print(io, indent, " ", m, ".", s, " = ", t)
else
# primary type binding
print(io, indent, " ")
dumptype(io, t, n - 1, string(indent, " "))
end
end
end
end
isempty(indent) && println(io)
nothing
end


# For abstract types, use _dumptype only if it's a form that will be called
# interactively.
dflt_io() = IOContext(STDOUT::IO, :limit => true)
dump(io::IO, x::DataType; maxdepth=8) = (x.abstract ? dumptype : dump)(io, x, maxdepth, "")
dump(x::DataType; maxdepth=8) = (x.abstract ? dumptype : dump)(dflt_io(), x, maxdepth, "")
dump(io::IO, x::DataType; maxdepth=8) = ((x.abstract ? dumptype : dump)(io, x, maxdepth, ""); println(io))

dump(io::IO, arg; maxdepth=8) = dump(io, arg, maxdepth, "")
dump(arg; maxdepth=8) = dump(dflt_io(), arg, maxdepth, "")
dump(io::IO, arg; maxdepth=8) = (dump(io, arg, maxdepth, ""); println(io))
dump(arg; maxdepth=8) = dump(IOContext(STDOUT::IO, :limit => true), arg; maxdepth=maxdepth)


"""
Expand Down
7 changes: 4 additions & 3 deletions base/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -986,13 +986,14 @@ function detect_ambiguities(mods...; imported::Bool=false)
ambs = Set{Tuple{Method,Method}}()
for mod in mods
for n in names(mod, true, imported)
Base.isdeprecated(mod, n) && continue
if !isdefined(mod, n)
println("Skipping ", mod, '.', n) # typically stale exports
continue
end
f = getfield(mod, n)
if isa(f, Function)
mt = methods(f)
if isa(f, DataType) && isdefined(f.name, :mt)
mt = Base.MethodList(f.name.mt)
for m in mt
if m.ambig !== nothing
for m2 in m.ambig
Expand All @@ -1005,7 +1006,7 @@ function detect_ambiguities(mods...; imported::Bool=false)
end
end
end
collect(ambs)
return collect(ambs)
end

"""
Expand Down
Loading

0 comments on commit d3a8988

Please sign in to comment.