run runnableExamples in the module scope (#11732) [feature]

This commit is contained in:
Timothee Cour
2019-07-22 07:22:57 -07:00
committed by Andreas Rumpf
parent 30f2cec671
commit 8c93c692b9
4 changed files with 81 additions and 17 deletions

View File

@@ -415,12 +415,6 @@ proc runAllExamples(d: PDoc) =
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
removeFile(outp.changeFileExt(ExeExt))
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
proc prepareExamples(d: PDoc; n: PNode) =
var docComment = newTree(nkCommentStmt)
@@ -430,12 +424,20 @@ proc prepareExamples(d: PDoc; n: PNode) =
docComment,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
for a in n.lastSon: runnableExamples.add a
testExample(d, runnableExamples)
when false:
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
if n.info.fileIndex != orig.info.fileIndex: return

View File

@@ -198,8 +198,8 @@ proc initUri*(): Uri =
## **See also:**
## * `Uri type <#Uri>`_ for available fields in the URI type
runnableExamples:
var uri: Uri
assert initUri() == uri
var uri2: Uri
assert initUri() == uri2
result = Uri(scheme: "", username: "", password: "", hostname: "", port: "",
path: "", query: "", anchor: "")

View File

@@ -128,7 +128,7 @@ when defined(nimHasRunnableExamples):
## a ``runnableExamples`` section is ignored.
## - The documentation generator is aware of these examples and considers them
## part of the ``##`` doc comment. As the last step of documentation
## generation the examples are put into an ``$file_example.nim`` file,
## generation each runnableExample is put in its own file ``$file_examples$i.nim``,
## compiled and tested. The collected examples are
## put into their own module to ensure the examples do not refer to
## non-exported symbols.
@@ -136,12 +136,14 @@ when defined(nimHasRunnableExamples):
## Usage:
##
## .. code-block:: Nim
## proc double(x: int): int =
## proc double*(x: int): int =
## ## This proc doubles a number.
## runnableExamples:
## ## at module scope
## assert double(5) == 10
## assert double(21) == 42
##
## block: ## at block scope
## defer: echo "done"
##
## result = 2 * x
else:
template runnableExamples*(body: untyped) =

View File

@@ -0,0 +1,60 @@
discard """
cmd: "nim doc $file"
action: "compile"
nimout: '''
foo1
foo2
foo3
foo5
foo6
foo7
foo8
foo9
'''
joinable: false
"""
proc fun*() =
runnableExamples:
block: # `defer` only allowed inside a block
defer: echo "foo1"
runnableExamples:
# `fun*` only allowed at top level
proc fun*()=echo "foo2"
fun()
block:
defer: echo "foo3"
runnableExamples:
# ditto
proc fun*()=echo "foo5"
fun()
runnableExamples:
# `codeReordering` only allowed at top level
{.experimental: "codeReordering".}
proc fun1() = fun2()
proc fun2() = echo "foo6"
fun1()
runnableExamples:
# only works at top level
import std/macros
macro myImport(a: static string): untyped =
newTree(nnkImportStmt, [newLit a])
myImport "str" & "utils"
doAssert declared(isAlphaAscii)
echo "foo7"
# also check for runnableExamples at module scope
runnableExamples:
block:
defer: echo "foo8"
runnableExamples:
proc fun*()=echo "foo9"
fun()
# note: there are yet other examples where putting runnableExamples at module
# scope is needed, for example when using an `include` before an `import`, etc.