diff --git a/src/DocTests.jl b/src/DocTests.jl index 11f7a2d3e8c..89171944abf 100644 --- a/src/DocTests.jl +++ b/src/DocTests.jl @@ -8,6 +8,7 @@ using DocStringExtensions import ..Documenter: Documenter, Documents, + Expanders, Utilities import Markdown, REPL @@ -64,12 +65,7 @@ function doctest(block::Markdown.Code, meta::Dict, doc::Documents.Document, page # Define new module or reuse an old one from this page if we have a named doctest. name = match(r"jldoctest[ ]?(.*)$", split(lang, ';', limit = 2)[1])[1] sym = isempty(name) ? gensym("doctest-") : Symbol("doctest-", name) - sandbox = get!(page.globals.meta, sym) do - newmod = Module(sym) - # eval(expr) is available in the REPL (i.e. Main) so we emulate that for the sandbox - Core.eval(newmod, :(eval(x) = Core.eval($newmod, x))) - newmod - end + sandbox = get!(() -> Expanders.get_new_sandbox(sym), page.globals.meta, sym) # Normalise line endings. block.code = replace(block.code, "\r\n" => "\n") diff --git a/src/Expanders.jl b/src/Expanders.jl index d66758105b0..81e0abb869d 100644 --- a/src/Expanders.jl +++ b/src/Expanders.jl @@ -459,7 +459,7 @@ function Selectors.runner(::Type{ExampleBlocks}, x, page, doc) # The sandboxed module -- either a new one or a cached one from this page. name = match(r"^@example[ ]?(.*)$", first(split(x.language, ';', limit = 2)))[1] sym = isempty(name) ? gensym("ex-") : Symbol("ex-", name) - mod = get!(page.globals.meta, sym, Module(sym))::Module + mod = get!(() -> get_new_sandbox(sym), page.globals.meta, sym) # "parse" keyword arguments to example (we only need to look for continued = true) continued = occursin(r"continued\s*=\s*true", x.language) @@ -529,7 +529,7 @@ function Selectors.runner(::Type{REPLBlocks}, x, page, doc) matched === nothing && error("invalid '@repl' syntax: $(x.language)") name = matched[1] sym = isempty(name) ? gensym("ex-") : Symbol("ex-", name) - mod = get!(page.globals.meta, sym, Module(sym))::Module + mod = get!(() -> get_new_sandbox(sym), page.globals.meta, sym) code = split(x.code, '\n'; limit = 2)[end] result, out = nothing, IOBuffer() for (ex, str) in Utilities.parseblock(x.code, doc, page) @@ -633,4 +633,13 @@ function prepend_prompt(input) rstrip(String(take!(out))) end +function get_new_sandbox(name::Symbol) + m = Module(name) + # eval(expr) is available in the REPL (i.e. Main) so we emulate that for the sandbox + Core.eval(m, :(eval(x) = Core.eval($m, x))) + # modules created with Module() does not have include defined + Core.eval(m, :(include(x) = Base.include($m, x))) + return m +end + end