fix https://github.com/nim-lang/RFCs/issues/352: show top-level import for top-level runnableExamples in generated docs (#17542)

* fix https://github.com/nim-lang/RFCs/issues/352: show top-level import for top-level runnableExamples in generated docs

* use canonical imoprt

* fix test
This commit is contained in:
Timothee Cour 2021-03-29 07:25:27 -07:00 • committed by GitHub
commit d23a757765
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 13 deletions

View file

@ -505,7 +505,7 @@ proc runAllExamples(d: PDoc) =
proc quoted(a: string): string = result.addQuoted(a) proc quoted(a: string): string = result.addQuoted(a)
proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] = proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, code: string] =
## returns `rdoccmd` and source code for this runnableExamples ## returns `rdoccmd` and source code for this runnableExamples
var rdoccmd = "" var rdoccmd = ""
if n.len < 2 or n.len > 3: globalError(d.conf, n.info, "runnableExamples invalid") if n.len < 2 or n.len > 3: globalError(d.conf, n.info, "runnableExamples invalid")
@ -556,7 +556,14 @@ $3
if rdoccmd notin d.exampleGroups: if rdoccmd notin d.exampleGroups:
d.exampleGroups[rdoccmd] = ExampleGroup(rdoccmd: rdoccmd, docCmd: d.conf.docCmd, index: d.exampleGroups.len) 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 d.exampleGroups[rdoccmd].code.add "import $1\n" % outp.string.quoted
result = (rdoccmd, code)
var codeShown: string
if topLevel: # refs https://github.com/nim-lang/RFCs/issues/352
let title = canonicalImport(d.conf, AbsoluteFile d.filename)
codeShown = "import $#\n$#" % [title, code]
else:
codeShown = code
result = (rdoccmd, codeShown)
when false: when false:
proc extractImports(n: PNode; result: PNode) = proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}: if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
@ -576,7 +583,7 @@ type RunnableState = enum
rsRunnable rsRunnable
rsDone rsDone
proc getAllRunnableExamplesImpl(d: PDoc; n: PNode, dest: var Rope, state: RunnableState): RunnableState = proc getAllRunnableExamplesImpl(d: PDoc; n: PNode, dest: var Rope, state: RunnableState, topLevel: bool): RunnableState =
##[ ##[
Simple state machine to tell whether we render runnableExamples and doc comments. Simple state machine to tell whether we render runnableExamples and doc comments.
This is to ensure that we can interleave runnableExamples and doc comments freely; This is to ensure that we can interleave runnableExamples and doc comments freely;
@ -601,7 +608,7 @@ proc getAllRunnableExamplesImpl(d: PDoc; n: PNode, dest: var Rope, state: Runnab
of nkCallKinds: of nkCallKinds:
if isRunnableExamples(n[0]) and if isRunnableExamples(n[0]) and
n.len >= 2 and n.lastSon.kind == nkStmtList and state in {rsStart, rsComment, rsRunnable}: n.len >= 2 and n.lastSon.kind == nkStmtList and state in {rsStart, rsComment, rsRunnable}:
let (rdoccmd, code) = prepareExample(d, n) let (rdoccmd, code) = prepareExample(d, n, topLevel)
var msg = "Example:" var msg = "Example:"
if rdoccmd.len > 0: msg.add " cmd: " & rdoccmd if rdoccmd.len > 0: msg.add " cmd: " & rdoccmd
dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n", dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n",
@ -652,19 +659,19 @@ proc getRoutineBody(n: PNode): PNode =
proc getAllRunnableExamples(d: PDoc, n: PNode, dest: var Rope) = proc getAllRunnableExamples(d: PDoc, n: PNode, dest: var Rope) =
var n = n var n = n
var state = rsStart var state = rsStart
template fn(n2) = template fn(n2, topLevel) =
state = getAllRunnableExamplesImpl(d, n2, dest, state) state = getAllRunnableExamplesImpl(d, n2, dest, state, topLevel)
dest.add genComment(d, n).rope dest.add genComment(d, n).rope
case n.kind case n.kind
of routineDefs: of routineDefs:
n = n.getRoutineBody n = n.getRoutineBody
case n.kind case n.kind
of nkCommentStmt, nkCallKinds: fn(n) of nkCommentStmt, nkCallKinds: fn(n, topLevel = false)
else: else:
for i in 0..<n.safeLen: for i in 0..<n.safeLen:
fn(n[i]) fn(n[i], topLevel = false)
if state == rsDone: return if state == rsDone: return
else: fn(n) else: fn(n, topLevel = true)
proc isVisible(d: PDoc; n: PNode): bool = proc isVisible(d: PDoc; n: PNode): bool =
result = false result = false

View file

@ -420,17 +420,21 @@ window.addEventListener('DOMContentLoaded', main);
<p class="module-desc">This is the top level module. <p class="module-desc">This is the top level module.
<p><strong class="examples_text">Example:</strong></p> <p><strong class="examples_text">Example:</strong></p>
<pre class="listing"><span class="Keyword">import</span><span class="Whitespace"> </span><span class="Identifier">subdir</span><span class="Whitespace"> </span><span class="Operator">/</span><span class="Whitespace"> </span><span class="Identifier">subdir_b</span><span class="Whitespace"> </span><span class="Operator">/</span><span class="Whitespace"> </span><span class="Identifier">utils</span><span class="Whitespace"> <pre class="listing"><span class="Keyword">import</span><span class="Whitespace"> </span><span class="Identifier">testproject</span><span class="Whitespace">
</span><span class="Keyword">import</span><span class="Whitespace"> </span><span class="Identifier">subdir</span><span class="Whitespace"> </span><span class="Operator">/</span><span class="Whitespace"> </span><span class="Identifier">subdir_b</span><span class="Whitespace"> </span><span class="Operator">/</span><span class="Whitespace"> </span><span class="Identifier">utils</span><span class="Whitespace">
</span><span class="Identifier">doAssert</span><span class="Whitespace"> </span><span class="Identifier">bar</span><span class="Punctuation">(</span><span class="DecNumber">3</span><span class="Punctuation">,</span><span class="Whitespace"> </span><span class="DecNumber">4</span><span class="Punctuation">)</span><span class="Whitespace"> </span><span class="Operator">==</span><span class="Whitespace"> </span><span class="DecNumber">7</span><span class="Whitespace"> </span><span class="Identifier">doAssert</span><span class="Whitespace"> </span><span class="Identifier">bar</span><span class="Punctuation">(</span><span class="DecNumber">3</span><span class="Punctuation">,</span><span class="Whitespace"> </span><span class="DecNumber">4</span><span class="Punctuation">)</span><span class="Whitespace"> </span><span class="Operator">==</span><span class="Whitespace"> </span><span class="DecNumber">7</span><span class="Whitespace">
</span><span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">enumValueA</span><span class="Punctuation">,</span><span class="Whitespace"> </span><span class="Identifier">enumValueB</span><span class="Punctuation">)</span><span class="Whitespace"> </span><span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">enumValueA</span><span class="Punctuation">,</span><span class="Whitespace"> </span><span class="Identifier">enumValueB</span><span class="Punctuation">)</span><span class="Whitespace">
</span><span class="Comment"># bug #11078</span><span class="Whitespace"> </span><span class="Comment"># bug #11078</span><span class="Whitespace">
</span><span class="Keyword">for</span><span class="Whitespace"> </span><span class="Identifier">x</span><span class="Whitespace"> </span><span class="Keyword">in</span><span class="Whitespace"> </span><span class="StringLit">&quot;xx&quot;</span><span class="Punctuation">:</span><span class="Whitespace"> </span><span class="Keyword">discard</span></pre>top2 </span><span class="Keyword">for</span><span class="Whitespace"> </span><span class="Identifier">x</span><span class="Whitespace"> </span><span class="Keyword">in</span><span class="Whitespace"> </span><span class="StringLit">&quot;xx&quot;</span><span class="Punctuation">:</span><span class="Whitespace"> </span><span class="Keyword">discard</span></pre>top2
<p><strong class="examples_text">Example:</strong></p> <p><strong class="examples_text">Example:</strong></p>
<pre class="listing"><span class="Keyword">discard</span><span class="Whitespace"> </span><span class="StringLit">&quot;in top2&quot;</span></pre>top2 after <pre class="listing"><span class="Keyword">import</span><span class="Whitespace"> </span><span class="Identifier">testproject</span><span class="Whitespace">
</span><span class="Keyword">discard</span><span class="Whitespace"> </span><span class="StringLit">&quot;in top2&quot;</span></pre>top2 after
<p><strong class="examples_text">Example:</strong></p> <p><strong class="examples_text">Example:</strong></p>
<pre class="listing"><span class="Keyword">discard</span><span class="Whitespace"> </span><span class="StringLit">&quot;in top3&quot;</span></pre>top3 after <pre class="listing"><span class="Keyword">import</span><span class="Whitespace"> </span><span class="Identifier">testproject</span><span class="Whitespace">
</span><span class="Keyword">discard</span><span class="Whitespace"> </span><span class="StringLit">&quot;in top3&quot;</span></pre>top3 after
<p><strong class="examples_text">Example:</strong></p> <p><strong class="examples_text">Example:</strong></p>
<pre class="listing"><span class="Identifier">assert</span><span class="Whitespace"> </span><span class="DecNumber">3</span><span class="Operator">*</span><span class="DecNumber">2</span><span class="Whitespace"> </span><span class="Operator">==</span><span class="Whitespace"> </span><span class="DecNumber">6</span></pre></p> <pre class="listing"><span class="Keyword">import</span><span class="Whitespace"> </span><span class="Identifier">testproject</span><span class="Whitespace">
</span><span class="Identifier">assert</span><span class="Whitespace"> </span><span class="DecNumber">3</span><span class="Operator">*</span><span class="DecNumber">2</span><span class="Whitespace"> </span><span class="Operator">==</span><span class="Whitespace"> </span><span class="DecNumber">6</span></pre></p>
<div class="section" id="6"> <div class="section" id="6">
<h1><a class="toc-backref" href="#6">Imports</a></h1> <h1><a class="toc-backref" href="#6">Imports</a></h1>
<dl class="item"> <dl class="item">