diff --git a/base/methodshow.jl b/base/methodshow.jl index d1f9a0fdf0846..18a1ecbf09f11 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -174,6 +174,7 @@ function url(m::Method) file = string(m.file) line = m.line line <= 0 || ismatch(r"In\[[0-9]+\]", file) && return "" + is_windows() && (file = replace(file, '\\', '/')) if inbase(M) if isempty(Base.GIT_VERSION_INFO.commit) # this url will only work if we're on a tagged release @@ -190,7 +191,7 @@ function url(m::Method) u = match(LibGit2.GITHUB_REGEX,u).captures[1] commit = string(LibGit2.head_oid(repo)) root = LibGit2.path(repo) - if startswith(file, root) + if startswith(file, root) || startswith(realpath(file), root) "https://github.com/$u/tree/$commit/"*file[length(root)+1:end]*"#L$line" else fileurl(file) diff --git a/test/pkg.jl b/test/pkg.jl index f815acb5816ef..65331f5bc259e 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -185,6 +185,13 @@ temp_pkg_dir() do Pkg.pin("Example", v"0.4.0") @test Pkg.update() == nothing Pkg.installed()["Example"] == v"0.4.0" + + # bug identified in #16850, Base.url \ vs / for non-Base methods + include(Pkg.dir("Example","src","Example.jl")) + meth = first(methods(Example.domath)) + fname = string(meth.file) + @test ('\\' in fname) == is_windows() + @test startswith(Base.url(meth), "https://github.com/JuliaLang/Example.jl/tree") end # add a directory that is not a git repository diff --git a/test/reflection.jl b/test/reflection.jl index 0a6a505e54555..7860e121de176 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -451,3 +451,50 @@ fLargeTable() = 4 # issue #15280 function f15280(x) end @test functionloc(f15280)[2] > 0 + +# bug found in #16850, Base.url with backslashes on Windows +function module_depth(from::Module, to::Module) + if from === to + return 0 + else + return 1 + module_depth(from, module_parent(to)) + end +end +function has_backslashes(mod::Module) + for n in names(mod, true, true) + isdefined(mod, n) || continue + f = getfield(mod, n) + if isa(f, Module) && module_depth(Main, f) <= module_depth(Main, mod) + continue + end + h = has_backslashes(f) + isnull(h) || return h + end + return Nullable{Method}() +end +function has_backslashes(f::Function) + for m in methods(f) + h = has_backslashes(m) + isnull(h) || return h + end + return Nullable{Method}() +end +function has_backslashes(meth::Method) + if '\\' in string(meth.file) + return Nullable{Method}(meth) + else + return Nullable{Method}() + end +end +has_backslashes(x) = Nullable{Method}() +h16850 = has_backslashes(Base) +if is_windows() + if isnull(h16850) + warn("No methods found in Base with backslashes in file name, ", + "skipping test for Base.url") + else + @test !('\\' in Base.url(get(h16850))) + end +else + @test isnull(h16850) +end