diff --git a/base/help.jl b/base/help.jl index 8af1b660255ee0..f0d6e8cca7039c 100644 --- a/base/help.jl +++ b/base/help.jl @@ -87,6 +87,18 @@ end func_expr_from_symbols(s::Vector{Symbol}) = length(s) == 1 ? s[1] : Expr(:., func_expr_from_symbols(s[1:end-1]), Expr(:quote, s[end])) +module_defined(x::Symbol) = isdefined(x) +module_defined(x::Expr) = + x.head == :. && + module_defined(x.args[1]) && + isdefined(eval(x.args[1]), x.args[2].value) + +function is_defined_in_module(name::AbstractString, obj::DataType, mod::AbstractString) + module_defined(parse(mod)) && + isdefined(eval(parse(mod)), symbol(name)) && + eval(parse("$mod.$name")) == obj +end + function help(io::IO, fname::AbstractString, obj=0) init_help() found = false @@ -104,6 +116,13 @@ function help(io::IO, fname::AbstractString, obj=0) append!(alldesc, FUNCTION_DICT[mfname]) found = true end + elseif isa(obj, DataType) + mfname = isempty(mod) ? fname : mod * "." * fname + if is_defined_in_module(fname, obj, mod) || + is_defined_in_module(fname, obj, "Base."*mod) + append!(alldesc, FUNCTION_DICT[mfname]) + found = true + end else append!(alldesc, FUNCTION_DICT[mfname]) found = true @@ -147,7 +166,7 @@ apropos(s::AbstractString) = apropos(STDOUT, s) function apropos(io::IO, txt::AbstractString) init_help() n = 0 - r = Regex("\\Q$txt", Base.PCRE.CASELESS) + r = Regex("\\Q$txt", "i") for (func, entries) in FUNCTION_DICT if ismatch(r, func) || any(e->ismatch(r,e), entries) for desc in entries @@ -166,8 +185,10 @@ function apropos(io::IO, txt::AbstractString) end end +typename(t::DataType) = t.name.name + help(io::IO, f::Function) = help(io, string(f), f) -help(io::IO, t::DataType) = help(io, string(t.name), t) +help(io::IO, t::DataType) = help(io, string(typename(t)), t) help(io::IO, t::Module) = help(io, string(t)) function help(io::IO, x) diff --git a/test/docs.jl b/test/docs.jl index 80033efce882d7..e8a6735408cf05 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -20,3 +20,70 @@ end @test (@doc ModuleMacroDoc) == "I am a module" @test (@doc ModuleMacroDoc.@m) == "I am a macro" + +# apropos function testing + +@test sprint(apropos, "non-documented object") == "No help information found.\n" + +# issue 11438 (partial) + +for (typ, name) in [ + (RoundingMode, "RoundingMode"), + (Dates.DateTime, "DateTime"), + (Libc.TmStruct, "TmStruct") + ] + @test sprint(help, typ) == sprint(help, name) +end + +module DataTypeHelpTest + +module M + type T end +end + +module N + type T end +end + +module P + module R + type U end + type T end + end + import .R.T +end + +const mod = string(current_module()) + +Base.Help.eval(quote + + init_help() + + import $(parse(mod)) + import $(parse(mod)): M, N, P + + const mod = $mod + + MODULE_DICT["T"] = ["$mod.M","$mod.N","$mod.P"] + MODULE_DICT["U"] = ["$mod.P","$mod.P.R"] + + FUNCTION_DICT["$mod.M.T"] = ["M.T"] + FUNCTION_DICT["$mod.N.T"] = ["N.T"] + FUNCTION_DICT["$mod.P.T"] = ["P.R.T"] + FUNCTION_DICT["$mod.P.U"] = ["P.U"] + FUNCTION_DICT["$mod.P.R.U"] = ["P.R.U"] + +end) + +import Base.Test.@test + +@test sprint(help, M.T) == "M.T\n" +@test sprint(help, N.T) == "N.T\n" +@test sprint(help, P.T) == "P.R.T\n" +@test sprint(help, P.R.U) == "P.R.U\n" +@test sprint(help, "$mod.M.T") == "M.T\n" +@test sprint(help, "$mod.N.T") == "N.T\n" +@test sprint(help, "$mod.P.T") == "P.R.T\n" +@test sprint(help, "$mod.P.R.U") == "P.R.U\n" +@test sprint(help, "T") == "M.T\n\nN.T\n\nP.R.T\n" +end