Fix non-toplevel fields in objects not getting rendered (#22266)

* Add example object into testproject

The proc is there to check the case of an identDef being inside an identDef (We do want to render those even if they are not exported)

* Add `inside` set to `TSrcGen` which allows us to see what context we are in

This is done instead of adding another inXyz bool parameter

We then use this to know if we are inside an object when rendering an nkIdentDefs (To know if we need to skip rendering it)

* Update test files
This commit is contained in:
Jake Leahy
2023-07-17 03:46:18 +10:00
committed by GitHub
parent 50d435cd39
commit 17915d93bf
5 changed files with 106 additions and 25 deletions

View File

@@ -31,6 +31,10 @@ type
length*: int16
sym*: PSym
Section = enum
GenericParams
ObjectDef
TRenderTokSeq* = seq[TRenderTok]
TSrcGen* = object
indent*: int
@@ -45,7 +49,7 @@ type
pendingWhitespace: int
comStack*: seq[PNode] # comment stack
flags*: TRenderFlags
inGenericParams: bool
inside: set[Section] # Keeps track of contexts we are in
checkAnon: bool # we're in a context that can contain sfAnon
inPragma: int
when defined(nimpretty):
@@ -73,6 +77,16 @@ proc isKeyword*(i: PIdent): bool =
(i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
result = true
proc isExported(n: PNode): bool =
## Checks if an ident is exported.
## This is meant to be used with idents in nkIdentDefs.
case n.kind
of nkPostfix:
n[0].ident.s == "*" and n[1].kind == nkIdent
of nkPragmaExpr:
n[0].isExported()
else: false
proc renderDefinitionName*(s: PSym, noQuotes = false): string =
## Returns the definition name of the symbol.
##
@@ -85,6 +99,25 @@ proc renderDefinitionName*(s: PSym, noQuotes = false): string =
else:
result = '`' & x & '`'
template inside(g: var TSrcGen, section: Section, body: untyped) =
## Runs `body` with `section` included in `g.inside`.
## Removes it at the end of the body if `g` wasn't inside it
## before the template.
let wasntInSection = section notin g.inside
g.inside.incl section
body
if wasntInSection:
g.inside.excl section
template outside(g: var TSrcGen, section: Section, body: untyped) =
## Temporarily removes `section` from `g.inside`. Adds it back
## at the end of the body if `g` was inside it before the template
let wasInSection = section in g.inside
g.inside.excl section
body
if wasInSection:
g.inside.incl section
const
IndentWidth = 2
longIndentWid = IndentWidth * 2
@@ -121,7 +154,7 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
g.flags = renderFlags
g.pendingNL = -1
g.pendingWhitespace = -1
g.inGenericParams = false
g.inside = {}
g.config = config
proc addTok(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
@@ -831,14 +864,12 @@ proc gproc(g: var TSrcGen, n: PNode) =
if n[patternPos].kind != nkEmpty:
gpattern(g, n[patternPos])
let oldInGenericParams = g.inGenericParams
g.inGenericParams = true
if renderNoBody in g.flags and n[miscPos].kind != nkEmpty and
n[miscPos][1].kind != nkEmpty:
gsub(g, n[miscPos][1])
else:
gsub(g, n[genericParamsPos])
g.inGenericParams = oldInGenericParams
g.inside(GenericParams):
if renderNoBody in g.flags and n[miscPos].kind != nkEmpty and
n[miscPos][1].kind != nkEmpty:
gsub(g, n[miscPos][1])
else:
gsub(g, n[genericParamsPos])
gsub(g, n[paramsPos])
if renderNoPragmas notin g.flags:
gsub(g, n[pragmasPos])
@@ -916,7 +947,7 @@ proc gasm(g: var TSrcGen, n: PNode) =
gsub(g, n[1])
proc gident(g: var TSrcGen, n: PNode) =
if g.inGenericParams and n.kind == nkSym:
if GenericParams in g.inside and n.kind == nkSym:
if sfAnon in n.sym.flags or
(n.typ != nil and tfImplicitTypeParam in n.typ.flags): return
@@ -1304,14 +1335,31 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
gsub(g, n, pragmasPos)
put(g, tkColon, ":")
gsub(g, n, bodyPos)
of nkConstDef, nkIdentDefs:
of nkIdentDefs:
# Skip if this is a property in a type and its not exported
# (While also not allowing rendering of non exported fields)
if ObjectDef in g.inside and (not n[0].isExported() and renderNonExportedFields notin g.flags):
return
# We render the identDef without being inside the section incase we render something like
# y: proc (x: string) # (We wouldn't want to check if x is exported)
g.outside(ObjectDef):
gcomma(g, n, 0, -3)
if n.len >= 2 and n[^2].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
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, "=")
gsub(g, n[^1], c)
of nkConstDef:
gcomma(g, n, 0, -3)
if n.len >= 2 and n[^2].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
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)
@@ -1468,20 +1516,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
of nkObjectTy:
if n.len > 0:
putWithSpace(g, tkObject, "object")
gsub(g, n[0])
gsub(g, n[1])
gcoms(g)
gsub(g, n[2])
g.inside(ObjectDef):
gsub(g, n[0])
gsub(g, n[1])
gcoms(g)
gsub(g, n[2])
else:
put(g, tkObject, "object")
of nkRecList:
indentNL(g)
for i in 0..<n.len:
if n[i].kind == nkIdentDefs and n[i][0].skipPragmaExpr.kind == nkPostfix or
renderNonExportedFields in g.flags:
optNL(g)
gsub(g, n[i], c)
gcoms(g)
optNL(g)
gsub(g, n[i], c)
gcoms(g)
dedent(g)
putNL(g)
of nkOfInherit:

View File

@@ -56,6 +56,12 @@
<ul class="simple simple-toc-section">
<li><a class="reference" href="#A" title="A {.inject.} = enum
aA">A</a></li>
<li><a class="reference" href="#AnotherObject" title="AnotherObject = object
case x*: bool
of true:
y*: proc (x: string)
of false:">AnotherObject</a></li>
<li><a class="reference" href="#B" title="B {.inject.} = enum
bB">B</a></li>
<li><a class="reference" href="#Foo" title="Foo = enum
@@ -368,6 +374,21 @@
The enum A.
</dd>
</div>
<div id="AnotherObject">
<dt><pre><a href="testproject.html#AnotherObject"><span class="Identifier">AnotherObject</span></a> <span class="Other">=</span> <span class="Keyword">object</span>
<span class="Keyword">case</span> <span class="Identifier">x</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">bool</span>
<span class="Keyword">of</span> <span class="Identifier">true</span><span class="Other">:</span>
<span class="Identifier">y</span><span class="Operator">*</span><span class="Other">:</span> <span class="Keyword">proc</span> <span class="Other">(</span><span class="Identifier">x</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span>
<span class="Keyword">of</span> <span class="Identifier">false</span><span class="Other">:</span>
</pre></dt>
<dd>
</dd>
</div>
<div id="B">
@@ -424,7 +445,7 @@
<div id="T19396">
<dt><pre><a href="testproject.html#T19396"><span class="Identifier">T19396</span></a> <span class="Other">=</span> <span class="Keyword">object</span>
<span class="Identifier">a</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span>
</pre></dt>
</pre></dt>
<dd>

View File

@@ -66,5 +66,6 @@ nim anything testproject.html#anything proc anything() 387
nim T19396 testproject.html#T19396 object T19396 392
nim somePragma testproject.html#somePragma.t template somePragma() 396
nim MyObject testproject.html#MyObject object MyObject 400
nim AnotherObject testproject.html#AnotherObject object AnotherObject 405
nimgrp bar testproject.html#bar-procs-all proc 31
nimgrp baz testproject.html#baz-procs-all proc 34

View File

@@ -52,6 +52,10 @@
<li><a class="reference external"
data-doc-search-tag="utils: template aEnum(): untyped" href="subdir/subdir_b/utils.html#aEnum.t">utils: template aEnum(): untyped</a></li>
</ul></dd>
<dt><a name="AnotherObject" href="#AnotherObject"><span>AnotherObject:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: object AnotherObject" href="testproject.html#AnotherObject">testproject: object AnotherObject</a></li>
</ul></dd>
<dt><a name="anything" href="#anything"><span>anything:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: proc anything()" href="testproject.html#anything">testproject: proc anything()</a></li>

View File

@@ -400,3 +400,11 @@ type # bug #21483
MyObject* = object
someString*: string ## This is a string
annotated* {.somePragma.}: string ## This is an annotated string
type
AnotherObject* = object
case x*: bool
of true:
y*: proc (x: string)
of false:
hidden: string