summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/docgen.nim65
-rw-r--r--compiler/renderer.nim2
-rw-r--r--lib/pure/sugar.nim5
-rw-r--r--tests/nimdoc/trunnableexamples.nim25
4 files changed, 70 insertions, 27 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index b09d08e6d..e902705fc 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -456,18 +456,6 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
 
 proc exampleOutputDir(d: PDoc): AbsoluteDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
 
-proc writeExample(d: PDoc; ex: PNode, rdoccmd: string) =
-  if d.conf.errorCounter > 0: return
-  let outputDir = d.exampleOutputDir
-  createDir(outputDir)
-  inc d.exampleCounter
-  let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
-      "_examples" & $d.exampleCounter & ".nim"))
-  #let nimcache = outp.changeFileExt"" & "_nimcache"
-  renderModule(ex, d.filename, outp.string, conf = d.conf)
-  if rdoccmd notin d.exampleGroups: d.exampleGroups[rdoccmd] = ExampleGroup(rdoccmd: rdoccmd, docCmd: d.conf.docCmd, index: d.exampleGroups.len)
-  d.exampleGroups[rdoccmd].code.add "import r\"$1\"\n" % outp.string
-
 proc runAllExamples(d: PDoc) =
   # This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
   # using `-d:js` (etc) cannot work properly, e.g. would fail with `importjs`
@@ -498,6 +486,8 @@ proc runAllExamples(d: PDoc) =
       rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
       # removeFile(outp.changeFileExt(ExeExt)) # it's in nimcache, no need to remove
 
+proc quoted(a: string): string = result.addQuoted(a)
+
 proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] =
   ## returns `rdoccmd` and source code for this runnableExamples
   var rdoccmd = ""
@@ -508,19 +498,48 @@ proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] =
     if n1.kind notin nkStrKinds: globalError(d.conf, n1.info, "string litteral expected")
     rdoccmd = n1.strVal
 
-  var docComment = newTree(nkCommentStmt)
+  let useRenderModule = false
   let loc = d.conf.toFileLineCol(n.info)
+  let code = extractRunnableExamplesSource(d.conf, n)
+
+  if d.conf.errorCounter > 0:
+    return (rdoccmd, code)
 
-  docComment.comment = "autogenerated by docgen\nloc: $1\nrdoccmd: $2" % [loc, rdoccmd]
-  var runnableExamples = newTree(nkStmtList,
-      docComment,
-      newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
-  runnableExamples.info = n.info
-  let ret = extractRunnableExamplesSource(d.conf, n)
-  for a in n.lastSon: runnableExamples.add a
-  # we could also use `ret` instead here, to keep sources verbatim
-  writeExample(d, runnableExamples, rdoccmd)
-  result = (rdoccmd, ret)
+  let comment = "autogenerated by docgen\nloc: $1\nrdoccmd: $2" % [loc, rdoccmd]
+  let outputDir = d.exampleOutputDir
+  createDir(outputDir)
+  inc d.exampleCounter
+  let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" & ("_examples$1.nim" % $d.exampleCounter)))
+
+  if useRenderModule:
+    var docComment = newTree(nkCommentStmt)
+    docComment.comment = comment
+    var runnableExamples = newTree(nkStmtList,
+        docComment,
+        newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
+    runnableExamples.info = n.info
+    for a in n.lastSon: runnableExamples.add a
+
+    # buggy, refs bug #17292
+    # still worth fixing as it can affect other code relying on `renderModule`,
+    # so we keep this code path here for now, which could still be useful in some
+    # other situations.
+    renderModule(runnableExamples, outp.string, conf = d.conf)
+
+  else:
+    let code2 = """
+#[
+$1
+]#
+import $2
+$3
+""" % [comment, d.filename.quoted, code]
+    writeFile(outp.string, code2)
+
+  if rdoccmd notin d.exampleGroups:
+    d.exampleGroups[rdoccmd] = ExampleGroup(rdoccmd: rdoccmd, docCmd: d.conf.docCmd, index: d.exampleGroups.len)
+  d.exampleGroups[rdoccmd].code.add "import $1\n" % outp.string.quoted
+  result = (rdoccmd, code)
   when false:
     proc extractImports(n: PNode; result: PNode) =
       if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 7c11b8225..ed1c52bb7 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1647,7 +1647,7 @@ proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string =
 
 proc `$`*(n: PNode): string = n.renderTree
 
-proc renderModule*(n: PNode, infile, outfile: string,
+proc renderModule*(n: PNode, outfile: string,
                    renderFlags: TRenderFlags = {};
                    fid = FileIndex(-1);
                    conf: ConfigRef = nil) =
diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim
index aa1cc5fb8..9654a0678 100644
--- a/lib/pure/sugar.nim
+++ b/lib/pure/sugar.nim
@@ -54,7 +54,6 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
 
 macro `=>`*(p, b: untyped): untyped =
   ## Syntax sugar for anonymous procedures. It also supports pragmas.
-  # TODO: xxx pending #13491: uncomment in runnableExamples
   runnableExamples:
     proc passTwoAndTwo(f: (int, int) -> int): int = f(2, 2)
 
@@ -69,8 +68,8 @@ macro `=>`*(p, b: untyped): untyped =
     myBot.call = (name: string) {.noSideEffect.} => "Hello " & name & ", I'm a bot."
     assert myBot.call("John") == "Hello John, I'm a bot."
 
-    # let f = () => (discard) # simplest proc that returns void
-    # f()
+    let f = () => (discard) # simplest proc that returns void
+    f()
 
   var
     params = @[ident"auto"]
diff --git a/tests/nimdoc/trunnableexamples.nim b/tests/nimdoc/trunnableexamples.nim
index 9e56e9143..2de1862bd 100644
--- a/tests/nimdoc/trunnableexamples.nim
+++ b/tests/nimdoc/trunnableexamples.nim
@@ -109,6 +109,31 @@ when true: # runnableExamples with rdoccmd
     # passing seq (to run with multiple compilation options)
     runnableExamples(@["-b:cpp", "-b:js"]): discard
 
+runnableExamples:
+  block: # bug #17279
+    when int.sizeof == 8:
+      let x = 0xffffffffffffffff
+      doAssert x == -1
+
+  # bug #13491
+  block:
+    proc fun(): int = doAssert false
+    doAssertRaises(AssertionError, (discard fun()))
+
+  block:
+    template foo(body) = discard
+    foo (discard)
+
+  block:
+    template fn(body: untyped): untyped = true
+    doAssert(fn do: nonexistant)
+  import std/macros
+  macro foo*(x, y) =
+    result = newLetStmt(x[0][0], x[0][1])
+  foo:
+    a = 1
+  do: discard
+
 # also check for runnableExamples at module scope
 runnableExamples:
   block: