diff options
author | Andrey Makarov <ph.makarov@gmail.com> | 2023-04-02 11:32:36 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-02 10:32:36 +0200 |
commit | 63b4b3c5b8c930ffc271c5e4e1a446e8616b2571 (patch) | |
tree | e5c589c3477f1f0beebae87e510b8b522ffcc830 | |
parent | 0c6f14af048c4bd61c91552af79c003dfd34601e (diff) | |
download | Nim-63b4b3c5b8c930ffc271c5e4e1a446e8616b2571.tar.gz |
Fix nim doc crash with group referencing & include (#21600)
This fixes a regression introduced in #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.
-rw-r--r-- | compiler/docgen.nim | 17 | ||||
-rw-r--r-- | lib/packages/docutils/rst.nim | 14 | ||||
-rw-r--r-- | nimdoc/testproject/expected/subdir/subdir_b/utils.html | 13 | ||||
-rw-r--r-- | nimdoc/testproject/expected/subdir/subdir_b/utils.idx | 3 | ||||
-rw-r--r-- | nimdoc/testproject/expected/theindex.html | 2 | ||||
-rw-r--r-- | nimdoc/testproject/subdir/subdir_b/utils_helpers.nim | 5 |
6 files changed, 40 insertions, 14 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 8105cc807..4a8e38054 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -112,13 +112,16 @@ type proc add(dest: var ItemPre, rst: PRstNode) = dest.add ItemFragment(isRst: true, rst: rst) proc add(dest: var ItemPre, str: string) = dest.add ItemFragment(isRst: false, str: str) -proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex = +proc addRstFileIndex(d: PDoc, fileIndex: lineinfos.FileIndex): rstast.FileIndex = let invalid = rstast.FileIndex(-1) - result = d.nimToRstFid.getOrDefault(info.fileIndex, default = invalid) + result = d.nimToRstFid.getOrDefault(fileIndex, default = invalid) if result == invalid: - let fname = toFullPath(d.conf, info) + let fname = toFullPath(d.conf, fileIndex) result = addFilename(d.sharedState, fname) - d.nimToRstFid[info.fileIndex] = result + d.nimToRstFid[fileIndex] = result + +proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex = + addRstFileIndex(d, info.fileIndex) proc cmpDecimalsIgnoreCase(a, b: string): int = ## 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 fileIndex: addRstFileIndex(d, nameNode.info)) addAnchorNim(d.sharedState, external = false, refn = symbolOrId, tooltip = detailedName, langSym = rstLangSymbol, - priority = symbolPriority(k), info = lineinfo) + priority = symbolPriority(k), info = lineinfo, + module = addRstFileIndex(d, FileIndex d.module.position)) let renderFlags = if nonExports: {renderNoBody, renderNoComments, renderDocComments, renderSyms, @@ -1451,7 +1455,8 @@ proc finishGenerateDoc*(d: var PDoc) = isGroup: true), priority = symbolPriority(k), # select index `0` just to have any meaningful warning: - info = overloadChoices[0].info) + info = overloadChoices[0].info, + module = addRstFileIndex(d, FileIndex d.module.position)) if optGenIndexOnly in d.conf.globalOptions: return diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index b3b1fb9c0..6d05a2454 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -350,7 +350,7 @@ type footnoteAnchor = "footnote anchor", headlineAnchor = "implicitly-generated headline anchor" AnchorSubst = object - info: TLineInfo # where the anchor was defined + info: TLineInfo # the file where the anchor was defined priority: int case kind: range[arInternalRst .. arNim] of arInternalRst: @@ -360,6 +360,7 @@ type anchorTypeExt: RstAnchorKind refnameExt: string of arNim: + module: FileIndex # anchor's module (generally not the same as file) tooltip: string # displayed tooltip for Nim-generated anchors langSym: LangSymbol refname: string # A reference name that will be inserted directly @@ -520,6 +521,9 @@ proc getFilename(filenames: RstFileTable, fid: FileIndex): string = proc getFilename(s: PRstSharedState, subst: AnchorSubst): string = getFilename(s.filenames, subst.info.fileIndex) +proc getModule(s: PRstSharedState, subst: AnchorSubst): string = + result = getFilename(s.filenames, subst.module) + proc currFilename(s: PRstSharedState): string = getFilename(s.filenames, s.currFileIdx) @@ -830,7 +834,7 @@ proc addAnchorExtRst(s: var PRstSharedState, key: string, refn: string, proc addAnchorNim*(s: var PRstSharedState, external: bool, refn: string, tooltip: string, langSym: LangSymbol, priority: int, - info: TLineInfo) = + info: TLineInfo, module: FileIndex) = ## Adds an anchor `refn`, which follows ## the rule `arNim` (i.e. a symbol in ``*.nim`` file) s.anchors.mgetOrPut(langSym.name, newSeq[AnchorSubst]()).add( @@ -859,7 +863,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode, for subst in substitutions: if subst.kind == arNim: if match(subst.langSym, langSym): - let key: GroupKey = (subst.langSym.symKind, getFilename(s, subst)) + let key: GroupKey = (subst.langSym.symKind, getModule(s, subst)) found.mgetOrPut(key, newSeq[AnchorSubst]()).add subst for key, sList in found: if sList.len == 1: @@ -880,7 +884,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode, break doAssert(foundGroup, "docgen has not generated the group for $1 (file $2)" % [ - langSym.name, getFilename(s, sList[0]) ]) + langSym.name, getModule(s, sList[0]) ]) proc findMainAnchorRst(s: PRstSharedState, linkText: string, info: TLineInfo): seq[AnchorSubst] = @@ -3552,7 +3556,7 @@ proc loadIdxFile(s: var PRstSharedState, origFilename: string) = langSym = langSymbolGroup(kind=entry.linkTitle, name=entry.keyword) addAnchorNim(s, external = true, refn = refn, tooltip = entry.linkDesc, langSym = langSym, priority = -4, # lowest - info=info) + info = info, module = info.fileIndex) doAssert s.idxImports[origFilename].title != "" proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) = diff --git a/nimdoc/testproject/expected/subdir/subdir_b/utils.html b/nimdoc/testproject/expected/subdir/subdir_b/utils.html index ee2618ab3..cfdac5310 100644 --- a/nimdoc/testproject/expected/subdir/subdir_b/utils.html +++ b/nimdoc/testproject/expected/subdir/subdir_b/utils.html @@ -106,6 +106,7 @@ <li><a class="reference" href="#fn2" title="fn2()">fn2()</a></li> <li><a class="reference" href="#fn2%2Cint" title="fn2(x: int)">fn2(x: int)</a></li> <li><a class="reference" href="#fn2%2Cint%2Cfloat" title="fn2(x: int; y: float)">fn2(x: int; y: float)</a></li> +<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> </ul> <ul class="simple nested-toc-section">fn3 @@ -215,7 +216,7 @@ <ol class="simple"><li>Other case value</li> <li>Second case.</li> </ol> -<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> +<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> <p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K; 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; 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 @@ <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> 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>. <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> -<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> +<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> <p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K; 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; 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; @@ -394,6 +395,14 @@ Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href= </dd> </div> +<div id="fn2,int,float,float"> + <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> + <dd> + + + + </dd> +</div> </div> <div id="fn3-procs-all"> diff --git a/nimdoc/testproject/expected/subdir/subdir_b/utils.idx b/nimdoc/testproject/expected/subdir/subdir_b/utils.idx index 81c2103e4..81b27bcb9 100644 --- a/nimdoc/testproject/expected/subdir/subdir_b/utils.idx +++ b/nimdoc/testproject/expected/subdir/subdir_b/utils.idx @@ -1,5 +1,6 @@ nimTitle utils subdir/subdir_b/utils.html module subdir/subdir_b/utils 0 nim funWithGenerics subdir/subdir_b/utils.html#funWithGenerics,T,U proc funWithGenerics[T, U: SomeFloat](a: T; b: U) 1 +nim fn2 subdir/subdir_b/utils.html#fn2,int,float,float proc fn2(x: int; y: float; z: float) 5 nim enumValueA subdir/subdir_b/utils.html#enumValueA SomeType.enumValueA 45 nim enumValueB subdir/subdir_b/utils.html#enumValueB SomeType.enumValueB 45 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 nim `'big` subdir/subdir_b/utils.html#'big,string proc `'big`(a: string): SomeType 164 nimgrp $ subdir/subdir_b/utils.html#$-procs-all proc 148 nimgrp fn11 subdir/subdir_b/utils.html#fN11-procs-all proc 85 -nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 57 +nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 5 nimgrp f subdir/subdir_b/utils.html#f-procs-all proc 130 heading This is now a header subdir/subdir_b/utils.html#this-is-now-a-header This is now a header 0 heading Next header subdir/subdir_b/utils.html#this-is-now-a-header-next-header Next header 0 diff --git a/nimdoc/testproject/expected/theindex.html b/nimdoc/testproject/expected/theindex.html index f9488eb2d..fd4666bf9 100644 --- a/nimdoc/testproject/expected/theindex.html +++ b/nimdoc/testproject/expected/theindex.html @@ -175,6 +175,8 @@ data-doc-search-tag="utils: proc fn2(x: int)" href="subdir/subdir_b/utils.html#fn2%2Cint">utils: proc fn2(x: int)</a></li> <li><a class="reference external" 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> + <li><a class="reference external" + 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> </ul></dd> <dt><a name="fn3" href="#fn3"><span>fn3:</span></a></dt><dd><ul class="simple"> <li><a class="reference external" diff --git a/nimdoc/testproject/subdir/subdir_b/utils_helpers.nim b/nimdoc/testproject/subdir/subdir_b/utils_helpers.nim index 2c45ffb83..d3f5edd29 100644 --- a/nimdoc/testproject/subdir/subdir_b/utils_helpers.nim +++ b/nimdoc/testproject/subdir/subdir_b/utils_helpers.nim @@ -1 +1,6 @@ proc funWithGenerics*[T, U: SomeFloat](a: T, b: U) = discard + +# We check that presence of overloaded `fn2` here does not break +# referencing in the "parent" file (the one that includes this one) +proc fn2*(x: int, y: float, z: float) = + discard |