diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2020-05-20 00:45:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-20 09:45:34 +0200 |
commit | 3d20f141939b0cb76079a9b0ae7784f7877f1698 (patch) | |
tree | ff6c7b9943309b0df409be3c15143ffad56b0e9f /compiler | |
parent | 4ae341353de5c58dc339e47b0eec2bbb4649dc10 (diff) | |
download | Nim-3d20f141939b0cb76079a9b0ae7784f7877f1698.tar.gz |
fix #10731 ; `runnableExamples "-b:cpp --run:off": code` works (#14384)
* runnableExamples "-b:cpp -r:off": code
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/docgen.nim | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 6123d49cf..8b5201029 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -17,7 +17,7 @@ import packages/docutils/rst, packages/docutils/rstgen, json, xmltree, cgi, trees, types, typesrenderer, astalgo, lineinfos, intsets, - pathutils, trees + pathutils, trees, tables const exportSection = skField @@ -26,6 +26,12 @@ const type TSections = array[TSymKind, Rope] + ExampleGroup = ref object + ## a group of runnableExamples with same rdoccmd + rdoccmd: string ## from 1st arg in `runnableExamples(rdoccmd): body` + docCmd: string ## from user config, eg --doccmd:-d:foo + code: string ## contains imports; each import contains `body` + index: int ## group index TDocumentor = object of rstgen.RstGenerator modDesc: Rope # module description module: PSym @@ -44,7 +50,7 @@ type # already. See bug #3655 destFile*: AbsoluteFile thisDir*: AbsoluteDir - examples: string + exampleGroups: OrderedTable[string, ExampleGroup] wroteCss*: bool PDoc* = ref TDocumentor ## Alias to type less. @@ -443,54 +449,72 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe dispA(d.conf, result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}", [escLit]) -proc testExample(d: PDoc; ex: PNode) = +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.conf.getNimcacheDir / RelativeDir"runnableExamples" + let outputDir = d.exampleOutputDir createDir(outputDir) inc d.exampleCounter + # PRTEMP 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) - d.examples.add "import r\"" & outp.string & "\"\n" + 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) = - let docCmd = d.conf.docCmd let backend = d.conf.backend # This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however # using `-d:js` (etc) cannot work properly, eg would fail with `importjs` # since semantics are affected by `config.backend`, not by isDefined(d.conf, "js") - if d.examples.len == 0 or docCmd == docCmdSkip: return - let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples" - let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" & - "_examples.nim")) - writeFile(outp, d.examples) - let cmd = "$nim $backend -r --warning:UnusedImport:off --path:$path --nimcache:$nimcache $docCmd $file" % [ - "nim", os.getAppFilename(), - "backend", $d.conf.backend, - "path", quoteShell(d.conf.projectPath), - "nimcache", quoteShell(outputDir), - "file", quoteShell(outp), - "docCmd", docCmd, - ] - if os.execShellCmd(cmd) != 0: - quit "[runnableExamples] failed: generated file: '$1' cmd: $2" % [outp.string, cmd] - else: - # keep generated source file `outp` to allow inspection. - rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string]) - removeFile(outp.changeFileExt(ExeExt)) - + let outputDir = d.exampleOutputDir + for _, group in d.exampleGroups: + if group.docCmd == docCmdSkip: continue + let outp = outputDir / RelativeFile("$1_group$2_examples.nim" % [d.filename.splitFile.name, $group.index]) + group.code = "# autogenerated by docgen\n# source: $1\n# rdoccmd: $2\n$3" % [d.filename, group.rdoccmd, group.code] + writeFile(outp, group.code) + # most useful semantics is that `docCmd` comes after `rdoccmd`, so that we can (temporarily) override + # via command line + let cmd = "$nim $backend -r --warning:UnusedImport:off --path:$path --nimcache:$nimcache $rdoccmd $docCmd $file" % [ + "nim", os.getAppFilename(), + "backend", $d.conf.backend, + "path", quoteShell(d.conf.projectPath), + "nimcache", quoteShell(outputDir), + "file", quoteShell(outp), + "rdoccmd", group.rdoccmd, + "docCmd", group.docCmd, + ] + if os.execShellCmd(cmd) != 0: + quit "[runnableExamples] failed: generated file: '$1' group: '$2' cmd: $3" % [outp.string, $group[], cmd] + else: + # keep generated source file `outp` to allow inspection. + rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string]) + # removeFile(outp.changeFileExt(ExeExt)) # it's in nimcache, no need to remove + +proc prepareExample(d: PDoc; n: PNode): string = + ## returns `rdoccmd` for this runnableExamples + var rdoccmd = "" + if n.len < 2 or n.len > 3: globalError(d.conf, n.info, "runnableExamples invalid") + if n.len == 3: + let n1 = n[1] + # xxx this should be evaluated during sempass + if n1.kind notin nkStrKinds: globalError(d.conf, n1.info, "string litteral expected") + rdoccmd = n1.strVal -proc prepareExamples(d: PDoc; n: PNode) = var docComment = newTree(nkCommentStmt) let loc = d.conf.toFileLineCol(n.info) - docComment.comment = "autogenerated by docgen from " & loc + + 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 + for a in n.lastSon: runnableExamples.add a - testExample(d, runnableExamples) + writeExample(d, runnableExamples, rdoccmd) + result = rdoccmd when false: proc extractImports(n: PNode; result: PNode) = if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}: @@ -510,9 +534,11 @@ proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) = of nkCallKinds: if isRunnableExamples(n[0]) and n.len >= 2 and n.lastSon.kind == nkStmtList: - prepareExamples(d, n) + let rdoccmd = prepareExample(d, n) + var msg = "Example:" + if rdoccmd.len > 0: msg.add " cmd: " & rdoccmd dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n", - "\n\\textbf{$1}\n", [rope"Examples:"]) + "\n\\textbf{$1}\n", [msg.rope]) inc d.listingCounter let id = $d.listingCounter dest.add(d.config.getOrDefault"doc.listing_start" % [id, "langNim"]) |