diff options
-rw-r--r-- | compiler/docgen.nim | 24 | ||||
-rw-r--r-- | lib/pure/uri.nim | 4 | ||||
-rw-r--r-- | lib/system.nim | 10 | ||||
-rw-r--r-- | tests/magics/trunnableexamples.nim | 60 |
4 files changed, 81 insertions, 17 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 2e03c0d4d..28cbcbd8d 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -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 diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index c0c78d735..088786f25 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -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: "") diff --git a/lib/system.nim b/lib/system.nim index a588a85b9..28eb1a1ef 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -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) = diff --git a/tests/magics/trunnableexamples.nim b/tests/magics/trunnableexamples.nim new file mode 100644 index 000000000..e6b2b70f8 --- /dev/null +++ b/tests/magics/trunnableexamples.nim @@ -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. |