diff options
author | awr1 <41453959+awr1@users.noreply.github.com> | 2018-09-04 16:33:52 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-04 16:33:52 -0500 |
commit | eb668003bf35671d7358e5f54e05820c0f4aef3d (patch) | |
tree | e5c5d6315f8ba4a5dd647bf67a4d0afb609916e7 /compiler/docgen.nim | |
parent | 89ad1cc9b18db8320e5b170ee45888cf79d52001 (diff) | |
parent | 4aba2981dd47672744191bd17b39bb149f494637 (diff) | |
download | Nim-eb668003bf35671d7358e5f54e05820c0f4aef3d.tar.gz |
Merge branch 'devel' into experimentalize-reorder
Diffstat (limited to 'compiler/docgen.nim')
-rw-r--r-- | compiler/docgen.nim | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index b35452365..23d156e05 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -14,7 +14,7 @@ import ast, strutils, strtabs, options, msgs, os, ropes, idents, wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast, - packages/docutils/rst, packages/docutils/rstgen, times, + packages/docutils/rst, packages/docutils/rstgen, packages/docutils/highlite, sempass2, json, xmltree, cgi, typesrenderer, astalgo, modulepaths, lineinfos, sequtils @@ -31,6 +31,7 @@ type isPureRst: bool conf*: ConfigRef cache*: IdentCache + exampleCounter: int PDoc* = ref TDocumentor ## Alias to type less. @@ -284,11 +285,56 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe dispA(d.conf, result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}", [rope(esc(d.target, literal))]) +proc testExample(d: PDoc; ex: PNode) = + if d.conf.errorCounter > 0: return + let outputDir = d.conf.getNimcacheDir / "runnableExamples" + createDir(outputDir) + inc d.exampleCounter + let outp = outputDir / extractFilename(d.filename.changeFileExt"" & + "_examples" & $d.exampleCounter & ".nim") + #let nimcache = outp.changeFileExt"" & "_nimcache" + renderModule(ex, d.filename, outp, conf = d.conf) + let backend = if isDefined(d.conf, "js"): "js" + elif isDefined(d.conf, "cpp"): "cpp" + elif isDefined(d.conf, "objc"): "objc" + else: "c" + if os.execShellCmd(os.getAppFilename() & " " & backend & + " --nimcache:" & outputDir & " -r " & outp) != 0: + quit "[Examples] failed: see " & outp + else: + # keep generated source file `outp` to allow inspection. + rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp]) + 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 runnableExamples = newTree(nkStmtList, + 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) + testExample(d, runnableExamples) + +proc isRunnableExample(n: PNode): bool = + # Templates and generics don't perform symbol lookups. + result = n.kind == nkSym and n.sym.magic == mRunnableExamples or + n.kind == nkIdent and n.ident.s == "runnableExamples" + proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) = case n.kind of nkCallKinds: - if n[0].kind == nkSym and n[0].sym.magic == mRunnableExamples and + if isRunnableExample(n[0]) and n.len >= 2 and n.lastSon.kind == nkStmtList: + prepareExamples(d, n) dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n", "\n\\textbf{$1}\n", [rope"Examples:"]) inc d.listingCounter @@ -627,6 +673,10 @@ proc generateDoc*(d: PDoc, n: PNode) = of nkImportStmt: for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i]) of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0]) + of nkCallKinds: + var comm: Rope = nil + getAllRunnableExamples(d, n, comm) + if comm > nil: add(d.modDesc, comm) else: discard proc add(d: PDoc; j: JsonNode) = @@ -787,14 +837,13 @@ proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string = proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) = var content = genOutFile(d) - var success = true if optStdout in d.conf.globalOptions: writeRope(stdout, content) else: let outfile = getOutFile2(d.conf, filename, outExt, "htmldocs") - success = writeRope(content, outfile) - if not success: - rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, filename) + createDir(outfile.parentDir) + if not writeRope(content, outfile): + rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, outfile) proc writeOutputJson*(d: PDoc, filename, outExt: string, useWarning = false) = |