summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJake Leahy <jake@leahy.dev>2022-12-12 17:44:17 +1100
committerGitHub <noreply@github.com>2022-12-12 07:44:17 +0100
commitcbeefc877cd752cd2e19a82fe3aa2914912f3182 (patch)
tree6cd20d98ddb88382d8e673bfa7c354ea16e04e60
parentb981f3eeb73bc2a8e068cf7dc7cf54c4362bf19e (diff)
downloadNim-cbeefc877cd752cd2e19a82fe3aa2914912f3182.tar.gz
Docs expand `using` parameters (#21076)
* Trying to fix by changing renderer

* add renderExpandUsing flag

This flag makes the renderer expand parameters that use using statement to have their full type

* Update docs

* Make comment better explain why checking for nkSym

* Fix nil access when macro/template has parameter with no type

* Fix nil access when node is not semmed yet
-rw-r--r--compiler/docgen.nim8
-rw-r--r--compiler/renderer.nim33
-rw-r--r--nimdoc/testproject/expected/testproject.html13
-rw-r--r--nimdoc/testproject/expected/testproject.idx1
-rw-r--r--nimdoc/testproject/expected/theindex.html2
-rw-r--r--nimdoc/testproject/testproject.nim5
6 files changed, 52 insertions, 10 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 0a24d2e09..fc37bd596 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -962,7 +962,7 @@ proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
       var literal = ""
       var r: TSrcGen
       initTokRender(r, genNode, {renderNoBody, renderNoComments,
-        renderNoPragmas, renderNoProcDefs})
+        renderNoPragmas, renderNoProcDefs, renderExpandUsing})
       var kind = tkEof
       while true:
         getNextTok(r, kind, literal)
@@ -995,7 +995,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
   var r: TSrcGen
   # Obtain the plain rendered string for hyperlink titles.
   initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments,
-    renderNoPragmas, renderNoProcDefs})
+    renderNoPragmas, renderNoProcDefs, renderExpandUsing})
   while true:
     getNextTok(r, kind, literal)
     if kind == tkEof:
@@ -1028,7 +1028,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
                rstLangSymbol, priority = symbolPriority(k), info = lineinfo)
 
   nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments,
-    renderDocComments, renderSyms}, symbolOrIdEnc)
+    renderDocComments, renderSyms, renderExpandUsing}, symbolOrIdEnc)
 
   let seeSrc = genSeeSrc(d, toFullPath(d.conf, n.info), n.info.line.int)
 
@@ -1094,7 +1094,7 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonItem =
     name = getName(d, nameNode)
     comm = genRecComment(d, n)
     r: TSrcGen
-  initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments})
+  initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments, renderExpandUsing})
   result.json = %{ "name": %name, "type": %($k), "line": %n.info.line.int,
                    "col": %n.info.col}
   if comm != nil:
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 15b712d0d..ad74cf2fe 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -24,7 +24,7 @@ type
   TRenderFlag* = enum
     renderNone, renderNoBody, renderNoComments, renderDocComments,
     renderNoPragmas, renderIds, renderNoProcDefs, renderSyms, renderRunnableExamples,
-    renderIr
+    renderIr, renderExpandUsing
   TRenderFlags* = set[TRenderFlag]
   TRenderTok* = object
     kind*: TokType
@@ -434,6 +434,24 @@ proc lsons(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
   result = 0
   for i in start..n.len + theEnd: inc(result, lsub(g, n[i]))
 
+proc origUsingType(n: PNode): PSym {.inline.} =
+  ## Returns the type that a parameter references. Check with referencesUsing first
+  ## to check `n` is actually referencing a using node
+  # If the node is untyped the typ field will be nil
+  if n[0].sym.typ != nil:
+    n[0].sym.typ.sym
+  else: nil
+
+proc referencesUsing(n: PNode): bool =
+  ## Returns true if n references a using statement.
+  ## e.g. proc foo(x) # x doesn't have type or def value so it references a using
+  result = n.kind == nkIdentDefs and
+           # Sometimes the node might not have been semmed (e.g. doc0) and will be nkIdent instead
+           n[0].kind == nkSym and
+           # Templates/macros can have parameters with no type (But their orig type will be nil)
+           n.origUsingType != nil and
+           n[1].kind == nkEmpty and n[2].kind == nkEmpty
+
 proc lsub(g: TSrcGen; n: PNode): int =
   # computes the length of a tree
   if isNil(n): return 0
@@ -474,8 +492,11 @@ proc lsub(g: TSrcGen; n: PNode): int =
   of nkDo: result = lsons(g, n) + len("do__:_")
   of nkConstDef, nkIdentDefs:
     result = lcomma(g, n, 0, - 3)
-    if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
-    if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
+    if n.referencesUsing:
+      result += lsub(g, newSymNode(n.origUsingType)) + 2
+    else:
+      if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
+      if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
   of nkVarTuple:
     if n[^1].kind == nkEmpty:
       result = lcomma(g, n, 0, - 2) + len("()")
@@ -1284,7 +1305,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
     gcomma(g, n, 0, -3)
     if n.len >= 2 and n[^2].kind != nkEmpty:
       putWithSpace(g, tkColon, ":")
-      gsub(g, n, n.len - 2)
+      gsub(g, n[^2], c)
+    elif n.referencesUsing and renderExpandUsing in g.flags:
+      putWithSpace(g, tkColon, ":")
+      gsub(g, newSymNode(n.origUsingType), c)
+
     if n.len >= 1 and n[^1].kind != nkEmpty:
       put(g, tkSpaces, Space)
       putWithSpace(g, tkEquals, "=")
diff --git a/nimdoc/testproject/expected/testproject.html b/nimdoc/testproject/expected/testproject.html
index 4caff7ec7..b68b721ff 100644
--- a/nimdoc/testproject/expected/testproject.html
+++ b/nimdoc/testproject/expected/testproject.html
@@ -116,7 +116,8 @@
 
 </ul>
 <ul class="simple nested-toc-section">bar
-  <li><a class="reference" href="#bar%2CT%2CT" title="bar[T](a, b: T): T">bar[T](a, b: T): T</a></li>
+  <li><a class="reference" href="#bar" title="bar(f: FooBuzz)">bar(f: FooBuzz)</a></li>
+<li><a class="reference" href="#bar%2CT%2CT" title="bar[T](a, b: T): T">bar[T](a, b: T): T</a></li>
 
 </ul>
 <ul class="simple nested-toc-section">baz
@@ -539,7 +540,15 @@
 
 </div>
 <div id="bar-procs-all">
-  <div id="bar,T,T">
+  <div id="bar">
+  <dt><pre><span class="Keyword">proc</span> <a href="#bar"><span class="Identifier">bar</span></a><span class="Other">(</span><span class="Identifier">f</span><span class="Other">:</span> <a href="testproject.html#FooBuzz"><span class="Identifier">FooBuzz</span></a><span class="Other">)</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
+  <dd>
+    
+    
+    
+  </dd>
+</div>
+<div id="bar,T,T">
   <dt><pre><span class="Keyword">proc</span> <a href="#bar%2CT%2CT"><span class="Identifier">bar</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">a</span><span class="Other">,</span> <span class="Identifier">b</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">T</span></pre></dt>
   <dd>
     
diff --git a/nimdoc/testproject/expected/testproject.idx b/nimdoc/testproject/expected/testproject.idx
index 4d0e63c0c..4d0172313 100644
--- a/nimdoc/testproject/expected/testproject.idx
+++ b/nimdoc/testproject/expected/testproject.idx
@@ -7,6 +7,7 @@ bar	testproject.html#bar,T,T	testproject: bar[T](a, b: T): T
 baz	testproject.html#baz,T,T	testproject: baz[T](a, b: T): T	
 buzz	testproject.html#buzz,T,T	testproject: buzz[T](a, b: T): T	
 FooBuzz	testproject.html#FooBuzz	testproject: FooBuzz	
+bar	testproject.html#bar	testproject: bar(f: FooBuzz)	
 aVariable	testproject.html#aVariable	testproject: aVariable	
 A	testproject.html#A	testproject: A	
 B	testproject.html#B	testproject: B	
diff --git a/nimdoc/testproject/expected/theindex.html b/nimdoc/testproject/expected/theindex.html
index 402541540..9f73040f2 100644
--- a/nimdoc/testproject/expected/theindex.html
+++ b/nimdoc/testproject/expected/theindex.html
@@ -78,6 +78,8 @@
           </ul></dd>
 <dt><a name="bar" href="#bar"><span>bar:</span></a></dt><dd><ul class="simple">
 <li><a class="reference external"
+          data-doc-search-tag="testproject: bar(f: FooBuzz)" href="testproject.html#bar">testproject: bar(f: FooBuzz)</a></li>
+          <li><a class="reference external"
           data-doc-search-tag="testproject: bar[T](a, b: T): T" href="testproject.html#bar%2CT%2CT">testproject: bar[T](a, b: T): T</a></li>
           <li><a class="reference external"
           data-doc-search-tag="testproject: bar(): untyped" href="testproject.html#bar.m">testproject: bar(): untyped</a></li>
diff --git a/nimdoc/testproject/testproject.nim b/nimdoc/testproject/testproject.nim
index 57960c69f..d236552ac 100644
--- a/nimdoc/testproject/testproject.nim
+++ b/nimdoc/testproject/testproject.nim
@@ -42,6 +42,11 @@ proc buzz*[T](a, b: T): T {.deprecated: "since v0.20".} =
 type
   FooBuzz* {.deprecated: "FooBuzz msg".} = int
 
+using f: FooBuzz
+
+proc bar*(f) = # `f` should be expanded to `f: FooBuzz`
+  discard
+
 import std/macros
 
 var aVariable*: array[1, int]