Skip to content

Commit 550a675

Browse files
a-mrbung87
authored andcommitted
Fix nim doc crash with group referencing & include (nim-lang#21600)
This fixes a regression introduced in nim-lang#20990 . When a group referencing is used and one of the overloaded symbols is in `include`d file, then `nim doc` crashes. The fix is in distinguishing (the index of) module and file where the symbol is defined, and using only module as the key in hash table for group referencing.
1 parent 1ec83c4 commit 550a675

File tree

6 files changed

+40
-14
lines changed

6 files changed

+40
-14
lines changed

compiler/docgen.nim

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,16 @@ type
112112
proc add(dest: var ItemPre, rst: PRstNode) = dest.add ItemFragment(isRst: true, rst: rst)
113113
proc add(dest: var ItemPre, str: string) = dest.add ItemFragment(isRst: false, str: str)
114114

115-
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
115+
proc addRstFileIndex(d: PDoc, fileIndex: lineinfos.FileIndex): rstast.FileIndex =
116116
let invalid = rstast.FileIndex(-1)
117-
result = d.nimToRstFid.getOrDefault(info.fileIndex, default = invalid)
117+
result = d.nimToRstFid.getOrDefault(fileIndex, default = invalid)
118118
if result == invalid:
119-
let fname = toFullPath(d.conf, info)
119+
let fname = toFullPath(d.conf, fileIndex)
120120
result = addFilename(d.sharedState, fname)
121-
d.nimToRstFid[info.fileIndex] = result
121+
d.nimToRstFid[fileIndex] = result
122+
123+
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
124+
addRstFileIndex(d, info.fileIndex)
122125

123126
proc cmpDecimalsIgnoreCase(a, b: string): int =
124127
## For sorting with correct handling of cases like 'uint8' and 'uint16'.
@@ -1060,7 +1063,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags, nonEx
10601063
fileIndex: addRstFileIndex(d, nameNode.info))
10611064
addAnchorNim(d.sharedState, external = false, refn = symbolOrId,
10621065
tooltip = detailedName, langSym = rstLangSymbol,
1063-
priority = symbolPriority(k), info = lineinfo)
1066+
priority = symbolPriority(k), info = lineinfo,
1067+
module = addRstFileIndex(d, FileIndex d.module.position))
10641068

10651069
let renderFlags =
10661070
if nonExports: {renderNoBody, renderNoComments, renderDocComments, renderSyms,
@@ -1451,7 +1455,8 @@ proc finishGenerateDoc*(d: var PDoc) =
14511455
isGroup: true),
14521456
priority = symbolPriority(k),
14531457
# select index `0` just to have any meaningful warning:
1454-
info = overloadChoices[0].info)
1458+
info = overloadChoices[0].info,
1459+
module = addRstFileIndex(d, FileIndex d.module.position))
14551460

14561461
if optGenIndexOnly in d.conf.globalOptions:
14571462
return

lib/packages/docutils/rst.nim

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ type
350350
footnoteAnchor = "footnote anchor",
351351
headlineAnchor = "implicitly-generated headline anchor"
352352
AnchorSubst = object
353-
info: TLineInfo # where the anchor was defined
353+
info: TLineInfo # the file where the anchor was defined
354354
priority: int
355355
case kind: range[arInternalRst .. arNim]
356356
of arInternalRst:
@@ -360,6 +360,7 @@ type
360360
anchorTypeExt: RstAnchorKind
361361
refnameExt: string
362362
of arNim:
363+
module: FileIndex # anchor's module (generally not the same as file)
363364
tooltip: string # displayed tooltip for Nim-generated anchors
364365
langSym: LangSymbol
365366
refname: string # A reference name that will be inserted directly
@@ -520,6 +521,9 @@ proc getFilename(filenames: RstFileTable, fid: FileIndex): string =
520521
proc getFilename(s: PRstSharedState, subst: AnchorSubst): string =
521522
getFilename(s.filenames, subst.info.fileIndex)
522523

524+
proc getModule(s: PRstSharedState, subst: AnchorSubst): string =
525+
result = getFilename(s.filenames, subst.module)
526+
523527
proc currFilename(s: PRstSharedState): string =
524528
getFilename(s.filenames, s.currFileIdx)
525529

@@ -830,7 +834,7 @@ proc addAnchorExtRst(s: var PRstSharedState, key: string, refn: string,
830834

831835
proc addAnchorNim*(s: var PRstSharedState, external: bool, refn: string, tooltip: string,
832836
langSym: LangSymbol, priority: int,
833-
info: TLineInfo) =
837+
info: TLineInfo, module: FileIndex) =
834838
## Adds an anchor `refn`, which follows
835839
## the rule `arNim` (i.e. a symbol in ``*.nim`` file)
836840
s.anchors.mgetOrPut(langSym.name, newSeq[AnchorSubst]()).add(
@@ -859,7 +863,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
859863
for subst in substitutions:
860864
if subst.kind == arNim:
861865
if match(subst.langSym, langSym):
862-
let key: GroupKey = (subst.langSym.symKind, getFilename(s, subst))
866+
let key: GroupKey = (subst.langSym.symKind, getModule(s, subst))
863867
found.mgetOrPut(key, newSeq[AnchorSubst]()).add subst
864868
for key, sList in found:
865869
if sList.len == 1:
@@ -880,7 +884,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
880884
break
881885
doAssert(foundGroup,
882886
"docgen has not generated the group for $1 (file $2)" % [
883-
langSym.name, getFilename(s, sList[0]) ])
887+
langSym.name, getModule(s, sList[0]) ])
884888

885889
proc findMainAnchorRst(s: PRstSharedState, linkText: string, info: TLineInfo):
886890
seq[AnchorSubst] =
@@ -3552,7 +3556,7 @@ proc loadIdxFile(s: var PRstSharedState, origFilename: string) =
35523556
langSym = langSymbolGroup(kind=entry.linkTitle, name=entry.keyword)
35533557
addAnchorNim(s, external = true, refn = refn, tooltip = entry.linkDesc,
35543558
langSym = langSym, priority = -4, # lowest
3555-
info=info)
3559+
info = info, module = info.fileIndex)
35563560
doAssert s.idxImports[origFilename].title != ""
35573561

35583562
proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) =

nimdoc/testproject/expected/subdir/subdir_b/utils.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ <h1 class="title">subdir/subdir_b/utils</h1>
106106
<li><a class="reference" href="#fn2" title="fn2()">fn2()</a></li>
107107
<li><a class="reference" href="#fn2%2Cint" title="fn2(x: int)">fn2(x: int)</a></li>
108108
<li><a class="reference" href="#fn2%2Cint%2Cfloat" title="fn2(x: int; y: float)">fn2(x: int; y: float)</a></li>
109+
<li><a class="reference" href="#fn2%2Cint%2Cfloat%2Cfloat" title="fn2(x: int; y: float; z: float)">fn2(x: int; y: float; z: float)</a></li>
109110

110111
</ul>
111112
<ul class="simple nested-toc-section">fn3
@@ -215,7 +216,7 @@ <h6><a class="toc-backref" id="more-headers-up-to-level-6" href="#more-headers-u
215216
<ol class="simple"><li>Other case value</li>
216217
<li>Second case.</li>
217218
</ol>
218-
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (3 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
219+
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (4 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
219220
<p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
220221
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
221222
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch(openArray[T], K, proc (T, K))</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
@@ -229,7 +230,7 @@ <h6><a class="toc-backref" id="more-headers-up-to-level-6" href="#more-headers-u
229230
<p>Group ref. with capital letters works: <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fN11</a> or <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fn11</a> </p>
230231
Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">[]</a> is the same as <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`(G[T])</a> because there are no overloads. The full form: <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`*[T](x: G[T]): T</a>Ref. <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">[]=</a> aka <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">`[]=`(G[T], int, T)</a>.Ref. <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">$</a> aka <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc $</a> or <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc `$`</a>.Ref. <a class="reference internal nimdoc" title="proc `$`[T](a: ref SomeType): string" href="#$,ref.SomeType">$(a: ref SomeType)</a>.Ref. <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">foo_bar</a> aka <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">iterator foo_bar_</a>.Ref. <a class="reference internal nimdoc" title="proc fn[T; U, V: SomeFloat]()" href="#fn">fn[T; U,V: SomeFloat]()</a>.Ref. <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">'big</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">func `'big`</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">`'big`(string)</a>.
231232
<h1><a class="toc-backref" id="pandoc-markdown" href="#pandoc-markdown">Pandoc Markdown</a></h1><p>Now repeat all the auto links of above in Pandoc Markdown Syntax.</p>
232-
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (3 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
233+
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (4 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
233234
<p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
234235
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
235236
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch(openArray[T], K, proc (T, K))</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
@@ -392,6 +393,14 @@ <h1><a class="toc-backref" href="#12">Procs</a></h1>
392393

393394

394395

396+
</dd>
397+
</div>
398+
<div id="fn2,int,float,float">
399+
<dt><pre><span class="Keyword">proc</span> <a href="#fn2%2Cint%2Cfloat%2Cfloat"><span class="Identifier">fn2</span></a><span class="Other">(</span><span class="Identifier">x</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">;</span> <span class="Identifier">y</span><span class="Other">:</span> <span class="Identifier">float</span><span class="Other">;</span> <span class="Identifier">z</span><span class="Other">:</span> <span class="Identifier">float</span><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>
400+
<dd>
401+
402+
403+
395404
</dd>
396405
</div>
397406

nimdoc/testproject/expected/subdir/subdir_b/utils.idx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
nimTitle utils subdir/subdir_b/utils.html module subdir/subdir_b/utils 0
22
nim funWithGenerics subdir/subdir_b/utils.html#funWithGenerics,T,U proc funWithGenerics[T, U: SomeFloat](a: T; b: U) 1
3+
nim fn2 subdir/subdir_b/utils.html#fn2,int,float,float proc fn2(x: int; y: float; z: float) 5
34
nim enumValueA subdir/subdir_b/utils.html#enumValueA SomeType.enumValueA 45
45
nim enumValueB subdir/subdir_b/utils.html#enumValueB SomeType.enumValueB 45
56
nim enumValueC subdir/subdir_b/utils.html#enumValueC SomeType.enumValueC 45
@@ -34,7 +35,7 @@ nim fn subdir/subdir_b/utils.html#fn proc fn[T; U, V: SomeFloat]() 160
3435
nim `'big` subdir/subdir_b/utils.html#'big,string proc `'big`(a: string): SomeType 164
3536
nimgrp $ subdir/subdir_b/utils.html#$-procs-all proc 148
3637
nimgrp fn11 subdir/subdir_b/utils.html#fN11-procs-all proc 85
37-
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 57
38+
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 5
3839
nimgrp f subdir/subdir_b/utils.html#f-procs-all proc 130
3940
heading This is now a header subdir/subdir_b/utils.html#this-is-now-a-header This is now a header 0
4041
heading Next header subdir/subdir_b/utils.html#this-is-now-a-header-next-header Next header 0

nimdoc/testproject/expected/theindex.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ <h1 class="title">Index</h1>
175175
data-doc-search-tag="utils: proc fn2(x: int)" href="subdir/subdir_b/utils.html#fn2%2Cint">utils: proc fn2(x: int)</a></li>
176176
<li><a class="reference external"
177177
data-doc-search-tag="utils: proc fn2(x: int; y: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat">utils: proc fn2(x: int; y: float)</a></li>
178+
<li><a class="reference external"
179+
data-doc-search-tag="utils: proc fn2(x: int; y: float; z: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat%2Cfloat">utils: proc fn2(x: int; y: float; z: float)</a></li>
178180
</ul></dd>
179181
<dt><a name="fn3" href="#fn3"><span>fn3:</span></a></dt><dd><ul class="simple">
180182
<li><a class="reference external"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
11
proc funWithGenerics*[T, U: SomeFloat](a: T, b: U) = discard
2+
3+
# We check that presence of overloaded `fn2` here does not break
4+
# referencing in the "parent" file (the one that includes this one)
5+
proc fn2*(x: int, y: float, z: float) =
6+
discard

0 commit comments

Comments
 (0)