diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index a85314ac2..8a6bf9287 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -83,10 +83,14 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
not c.isDeclarative:
c.isDeclarative = true
isDeclarative = true
- var res = copyNode(c, templ, actual)
- for i in 0..`_.
+ runnableExamples: assert 1 == 1
+ runnableExamples("--assertions:off"):
+ assert 1 == 2 # no code generated, no failure here
+ runnableExamples("-d:danger"): assert 1 == 2 # ditto
assertImpl(cond, msg, astToStr(cond), compileOption("assertions"))
template doAssert*(cond: untyped, msg = "") =
## Similar to `assert <#assert.t,untyped,string>`_ but is always turned on regardless of `--assertions`.
+ runnableExamples:
+ doAssert 1 == 1 # generates code even when built with `-d:danger` or `--assertions:off`
assertImpl(cond, msg, astToStr(cond), true)
template onFailedAssert*(msg, code: untyped): untyped {.dirty.} =
## Sets an assertion failure handler that will intercept any assert
## statements following `onFailedAssert` in the current scope.
+ runnableExamples:
+ type MyError = object of CatchableError
+ lineinfo: tuple[filename: string, line: int, column: int]
+ # block-wide policy to change the failed assert exception type in order to
+ # include a lineinfo
+ onFailedAssert(msg):
+ raise (ref MyError)(msg: msg, lineinfo: instantiationInfo(-2))
+ doAssertRaises(MyError): doAssert false
template failedAssertImpl(msgIMPL: string): untyped {.dirty.} =
let msg = msgIMPL
code
template doAssertRaises*(exception: typedesc, code: untyped) =
## Raises `AssertionDefect` if specified `code` does not raise `exception`.
+ runnableExamples:
+ doAssertRaises(ValueError): raise newException(ValueError, "Hello World")
+ doAssertRaises(CatchableError): raise newException(ValueError, "Hello World")
+ doAssertRaises(AssertionDefect): doAssert false
var wrong = false
const begin = "expected raising '" & astToStr(exception) & "', instead"
const msgEnd = " by: " & astToStr(code)
diff --git a/nimdoc/testproject/expected/subdir/subdir_b/utils.html b/nimdoc/testproject/expected/subdir/subdir_b/utils.html
index 794066cae..826cad02a 100644
--- a/nimdoc/testproject/expected/subdir/subdir_b/utils.html
+++ b/nimdoc/testproject/expected/subdir/subdir_b/utils.html
@@ -206,9 +206,9 @@ constructor.
template fromUtilsGen(): untyped
-this should be shown in utils.html
+should be shown in utils.html only
Example:
-assert 3*2 == 6
ditto
+discard "should be in utils.html only, not in module that calls fromUtilsGen"
ditto
diff --git a/nimdoc/testproject/expected/testproject.html b/nimdoc/testproject/expected/testproject.html
index d2fe38021..513dd507b 100644
--- a/nimdoc/testproject/expected/testproject.html
+++ b/nimdoc/testproject/expected/testproject.html
@@ -431,10 +431,7 @@ window.addEventListener('DOMContentLoaded', main);
discard "in top2"top2 after
Example:
import testproject
-discard "in top3"
top3 after
-Example:
-import testproject
-assert 3*2 == 6
+discard "in top3"top3 after
@@ -574,7 +571,8 @@ My someFunc. Stuff in fromUtilsGen is called
Example:
-discard 1
+discard """should be shown as examples for fromUtils3
+ in module calling fromUtilsGen"""
@@ -957,6 +955,9 @@ cz18
-
ok3
+
Example:
+discard """should be shown as examples for fromUtils2
+ in module calling fromUtilsGen"""
diff --git a/nimdoc/testproject/subdir/subdir_b/utils.nim b/nimdoc/testproject/subdir/subdir_b/utils.nim
index 128e8e481..4e3aa1f10 100644
--- a/nimdoc/testproject/subdir/subdir_b/utils.nim
+++ b/nimdoc/testproject/subdir/subdir_b/utils.nim
@@ -50,9 +50,9 @@ template bEnum*(): untyped =
discard
template fromUtilsGen*(): untyped =
- ## this should be shown in utils.html
+ ## should be shown in utils.html only
runnableExamples:
- assert 3*2 == 6
+ discard "should be in utils.html only, not in module that calls fromUtilsGen"
## ditto
iterator fromUtils1*(): int =
@@ -64,7 +64,11 @@ template fromUtilsGen*(): untyped =
template fromUtils2*() =
## ok3
+ runnableExamples:
+ discard """should be shown as examples for fromUtils2
+ in module calling fromUtilsGen"""
proc fromUtils3*() =
## came form utils but should be shown where `fromUtilsGen` is called
- runnableExamples: discard 1
+ runnableExamples: discard """should be shown as examples for fromUtils3
+ in module calling fromUtilsGen"""
diff --git a/tests/js/tstdlib_various.nim b/tests/js/tstdlib_various.nim
index a1bb63d46..4b5ce1de8 100644
--- a/tests/js/tstdlib_various.nim
+++ b/tests/js/tstdlib_various.nim
@@ -153,7 +153,7 @@ block tsplit2:
var errored = false
try:
discard "hello".split("")
- except AssertionError:
+ except AssertionDefect:
errored = true
doAssert errored
diff --git a/tests/nimdoc/trunnableexamples.nim b/tests/nimdoc/trunnableexamples.nim
index bc5ea0e5e..ac7a0e26f 100644
--- a/tests/nimdoc/trunnableexamples.nim
+++ b/tests/nimdoc/trunnableexamples.nim
@@ -1,6 +1,7 @@
discard """
-cmd: "nim doc --doccmd:-d:testFooExternal --hints:off $file"
+cmd: "nim doc --doccmd:--hints:off --hints:off $file"
action: "compile"
+nimoutFull: true
nimout: '''
foo1
foo2
@@ -8,12 +9,23 @@ foo3
foo5
foo6
foo7
+in examplesInTemplate1
+doc in outer
+doc in inner1
+doc in inner2
foo8
foo9
'''
joinable: false
"""
+#[
+pending bug #18077, use instead:
+cmd: "nim doc --doccmd:'-d:testFooExternal --hints:off' --hints:off $file"
+and merge trunnableexamples2 back here
+]#
+{.define(testFooExternal).}
+
proc fun*() =
runnableExamples:
block: # `defer` only allowed inside a block
@@ -109,6 +121,47 @@ when true: # runnableExamples with rdoccmd
# passing seq (to run with multiple compilation options)
runnableExamples(@["-b:cpp", "-b:js"]): discard
+when true: # bug #16993
+ template examplesInTemplate1*(cond: untyped) =
+ ## in examplesInTemplate1
+ runnableExamples:
+ echo "in examplesInTemplate1"
+ discard
+ examplesInTemplate1 true
+ examplesInTemplate1 true
+ examplesInTemplate1 true
+
+when true: # bug #18054
+ template outer*(body: untyped) =
+ ## outer template doc string.
+ runnableExamples:
+ echo "doc in outer"
+ ##
+ template inner1*() =
+ ## inner1 template doc string.
+ runnableExamples:
+ echo "doc in inner1"
+ ##
+
+ template inner2*() =
+ ## inner2 template doc string.
+ runnableExamples:
+ echo "doc in inner2"
+ body
+ outer:
+ inner1()
+ inner2()
+
+when true: # bug #17835
+ template anyItFake*(s, pred: untyped): bool =
+ ## Foo
+ runnableExamples: discard
+ true
+
+ proc anyItFakeMain*(n: seq[int]): bool =
+ result = anyItFake(n, it == 0)
+ # this was giving: Error: runnableExamples must appear before the first non-comment statement
+
runnableExamples:
block: # bug #17279
when int.sizeof == 8:
@@ -118,7 +171,7 @@ runnableExamples:
# bug #13491
block:
proc fun(): int = doAssert false
- doAssertRaises(AssertionError, (discard fun()))
+ doAssertRaises(AssertionDefect, (discard fun()))
block:
template foo(body) = discard
diff --git a/tests/nimdoc/trunnableexamples2.nim b/tests/nimdoc/trunnableexamples2.nim
new file mode 100644
index 000000000..5a437744e
--- /dev/null
+++ b/tests/nimdoc/trunnableexamples2.nim
@@ -0,0 +1,11 @@
+discard """
+cmd: "nim doc --doccmd:-d:testFooExternal --hints:off $file"
+action: "compile"
+joinable: false
+"""
+
+# pending bug #18077, merge back inside trunnableexamples.nim
+when true: # runnableExamples with rdoccmd
+ runnableExamples "-d:testFoo -d:testBar":
+ doAssert defined(testFoo) and defined(testBar)
+ doAssert defined(testFooExternal)