Skip to content

Commit 55fed89

Browse files
toreinioQt Cherry-pick Bot
authored andcommitted
qdoc: Fix links for access functions associated with multiple properties
FunctionNode::hasOneAssociatedProperty() was used for resolving where to link to for undocumented property access functions. If a function is undocumented, it should link to the property where QDoc auto-generates the list of access functions. This broke down if there are multiple properties associated with, for example, an undocumented notifier signal. There, QDoc gave up and just generated a non-existent anchor for the signal, resulting in broken intra-page links. To fix, replace hasOneAssociatedProperty() with a function that returns a `primary` associated property to get consistent linking. A property is considered a primary for an access function if the function name appears at the start of the property name. Fixes: QTBUG-128356 Change-Id: Ie23fe62bb97f3f883c794bd94042c4d376f45699 Reviewed-by: Paul Wicking <[email protected]> (cherry picked from commit c95c68a) Reviewed-by: Qt Cherry-pick Bot <[email protected]>
1 parent 83bed60 commit 55fed89

File tree

16 files changed

+149
-13
lines changed

16 files changed

+149
-13
lines changed

src/qdoc/qdoc/src/qdoc/functionnode.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,33 @@ void FunctionNode::addAssociatedProperty(PropertyNode *p)
319319
m_associatedProperties.append(p);
320320
}
321321

322+
/*!
323+
Returns the \e primary associated property, if this is an
324+
access function for one or more properties.
325+
326+
An associated property is considered a primary if this
327+
function's name starts with the property name. If there's
328+
no such property, return the first one available as a
329+
fallback.
330+
331+
If no associated properties exist, returns \nullptr.
332+
*/
333+
const PropertyNode *FunctionNode::primaryAssociatedProperty() const
334+
{
335+
if (m_associatedProperties.isEmpty())
336+
return nullptr;
337+
if (m_associatedProperties.size() == 1)
338+
return m_associatedProperties[0];
339+
340+
auto it = std::find_if(
341+
m_associatedProperties.cbegin(), m_associatedProperties.cend(),
342+
[this](const PropertyNode *p) {
343+
return name().startsWith(p->name());
344+
});
345+
346+
return it != m_associatedProperties.cend() ? *it : m_associatedProperties[0];
347+
}
348+
322349
/*!
323350
\reimp
324351

src/qdoc/qdoc/src/qdoc/functionnode.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,7 @@ class FunctionNode : public Node
119119
[[nodiscard]] const QString &overridesThis() const { return m_overridesThis; }
120120
[[nodiscard]] const QList<PropertyNode *> &associatedProperties() const { return m_associatedProperties; }
121121
[[nodiscard]] bool hasAssociatedProperties() const { return !m_associatedProperties.isEmpty(); }
122-
[[nodiscard]] bool hasOneAssociatedProperty() const
123-
{
124-
return (m_associatedProperties.size() == 1);
125-
}
122+
[[nodiscard]] const PropertyNode *primaryAssociatedProperty() const;
126123
[[nodiscard]] QString element() const override { return parent()->name(); }
127124
[[nodiscard]] bool isAttached() const override { return m_attached; }
128125
[[nodiscard]] QString qmlTypeName() const override { return parent()->qmlTypeName(); }

src/qdoc/qdoc/src/qdoc/generator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,8 @@ QString Generator::fullDocumentLocation(const Node *node)
492492
default:
493493
if (fn->isDtor())
494494
anchorRef = "#dtor." + fn->name().mid(1);
495-
else if (fn->hasOneAssociatedProperty() && fn->doc().isEmpty())
496-
return fullDocumentLocation(fn->associatedProperties()[0]);
495+
else if (const auto *p = fn->primaryAssociatedProperty(); p && fn->doc().isEmpty())
496+
return fullDocumentLocation(p);
497497
else if (fn->overloadNumber() > 0)
498498
anchorRef = QLatin1Char('#') + cleanRef(fn->name()) + QLatin1Char('-')
499499
+ QString::number(fn->overloadNumber());

src/qdoc/qdoc/src/qdoc/xmlgenerator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ QString XmlGenerator::refForNode(const Node *node)
280280
ref += QLatin1Char('-') + QString::number(fn->overloadNumber());
281281
break;
282282
default:
283-
if (fn->hasOneAssociatedProperty() && fn->doc().isEmpty()) {
284-
return refForNode(fn->associatedProperties()[0]);
283+
if (const auto *p = fn->primaryAssociatedProperty(); p && fn->doc().isEmpty()) {
284+
return refForNode(p);
285285
} else {
286286
ref = fn->name();
287287
if (fn->overloadNumber() != 0)

src/qdoc/qdoc/tests/validateqdocoutputfiles/testdata/comprehensiveproject/expected/docbook/testqdoc-testderived.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,38 @@
185185
</db:listitem>
186186
</db:itemizedlist>
187187
</db:section>
188+
<db:section xml:id="secondBoolProp-prop">
189+
<db:title its:translate="no">[read-only] secondBoolProp : const bool</db:title>
190+
<db:fieldsynopsis>
191+
<db:modifier>(Qt property)</db:modifier>
192+
<db:type>bool</db:type>
193+
<db:varname>secondBoolProp</db:varname>
194+
<db:synopsisinfo role="access">public</db:synopsisinfo>
195+
<db:synopsisinfo role="status">active</db:synopsisinfo>
196+
<db:synopsisinfo role="threadsafeness">unspecified</db:synopsisinfo>
197+
<db:synopsisinfo role="getter">secondBoolProp</db:synopsisinfo>
198+
<db:synopsisinfo role="notifier">boolPropChanged</db:synopsisinfo>
199+
</db:fieldsynopsis>
200+
<db:para>A property sharing a notifier signal with <db:link xlink:href="testqdoc-testderived.xml#boolProp-prop">boolProp</db:link>.</db:para>
201+
<db:para>
202+
<db:emphasis role="bold">Access functions:
203+
</db:emphasis>
204+
</db:para>
205+
<db:itemizedlist its:translate="no">
206+
<db:listitem>
207+
<db:para><db:type>bool</db:type> <db:emphasis role="bold"><db:link xlink:href="">secondBoolProp</db:link></db:emphasis>()</db:para>
208+
</db:listitem>
209+
</db:itemizedlist>
210+
<db:para>
211+
<db:emphasis role="bold">Notifier signal:
212+
</db:emphasis>
213+
</db:para>
214+
<db:itemizedlist its:translate="no">
215+
<db:listitem>
216+
<db:para><db:type>void</db:type> <db:emphasis role="bold"><db:link xlink:href="testqdoc-testderived.xml#boolProp-prop">boolPropChanged</db:link></db:emphasis>()</db:para>
217+
</db:listitem>
218+
</db:itemizedlist>
219+
</db:section>
188220
<db:section xml:id="someProp-prop">
189221
<db:title its:translate="no">[bindable read-only] someProp : QString</db:title>
190222
<db:fieldsynopsis>

src/qdoc/qdoc/tests/validateqdocoutputfiles/testdata/comprehensiveproject/expected/html/test.index

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,14 @@
149149
<function name="bindableProp" fullname="TestQDoc::TestDerived::bindableProp" href="testqdoc-testderived.html#bindableProp-prop" status="active" access="public" location="testcpp.h" meta="plain" associated-property="bindableProp" type="QBindable&lt;QString&gt;" signature="QBindable&lt;QString&gt; bindableProp()"/>
150150
<function name="bindablePropChanged" fullname="TestQDoc::TestDerived::bindablePropChanged" href="testqdoc-testderived.html#bindableProp-prop" status="active" access="public" location="testcpp.h" meta="signal" associated-property="bindableProp" type="void" signature="void bindablePropChanged()"/>
151151
<function name="boolProp" fullname="TestQDoc::TestDerived::boolProp" href="testqdoc-testderived.html#boolProp-prop" status="active" access="public" location="testcpp.h" meta="plain" associated-property="boolProp" type="bool" signature="bool boolProp()"/>
152-
<function name="boolPropChanged" fullname="TestQDoc::TestDerived::boolPropChanged" href="testqdoc-testderived.html#boolProp-prop" status="active" access="public" location="testcpp.h" meta="signal" associated-property="boolProp" type="void" signature="void boolPropChanged()"/>
152+
<function name="boolPropChanged" fullname="TestQDoc::TestDerived::boolPropChanged" href="testqdoc-testderived.html#boolProp-prop" status="active" access="public" location="testcpp.h" meta="signal" associated-property="boolProp,secondBoolProp" type="void" signature="void boolPropChanged()"/>
153153
<function name="emitSomething" fullname="TestQDoc::TestDerived::emitSomething" href="testqdoc-testderived.html#emitSomething" status="active" access="public" location="testcpp.h" documented="true" meta="signal" type="void" signature="void emitSomething()"/>
154154
<function name="getInt" fullname="TestQDoc::TestDerived::getInt" href="testqdoc-testderived.html#intProp-prop" status="active" access="public" location="testcpp.h" meta="plain" associated-property="intProp" type="int *" signature="int * getInt()"/>
155155
<function name="id" fullname="TestQDoc::TestDerived::id" href="testqdoc-testderived.html#id" status="active" access="public" location="testcpp.h" documented="true" meta="plain" virtual="virtual" override="true" type="int" signature="int id() override"/>
156156
<function name="invokeMe" fullname="TestQDoc::TestDerived::invokeMe" href="testqdoc-testderived.html#invokeMe" status="active" access="public" location="testcpp.h" documented="true" meta="plain" const="true" type="void" brief="Something invokable" signature="void invokeMe() const"/>
157157
<function name="name" fullname="TestQDoc::TestDerived::name" href="testqdoc-testderived.html#name-prop" status="active" access="public" location="testcpp.h" meta="plain" const="true" associated-property="name" type="const QString *" signature="const QString * name() const"/>
158158
<function name="resetBoolProp" fullname="TestQDoc::TestDerived::resetBoolProp" href="testqdoc-testderived.html#boolProp-prop" status="active" access="public" location="testcpp.h" meta="slot" associated-property="boolProp" type="void" signature="void resetBoolProp()"/>
159+
<function name="secondBoolProp" fullname="TestQDoc::TestDerived::secondBoolProp" href="testqdoc-testderived.html#secondBoolProp-prop" status="active" access="public" location="testcpp.h" meta="plain" associated-property="secondBoolProp" type="bool" signature="bool secondBoolProp()"/>
159160
<function name="setBindableProp" fullname="TestQDoc::TestDerived::setBindableProp" href="testqdoc-testderived.html#bindableProp-prop" status="active" access="public" location="testcpp.h" meta="slot" associated-property="bindableProp" type="void" signature="void setBindableProp(const QString &amp;s)">
160161
<parameter type="const QString &amp;" name="s" default=""/>
161162
</function>
@@ -185,6 +186,10 @@
185186
<property name="name" fullname="TestQDoc::TestDerived::name" href="testqdoc-testderived.html#name-prop" status="active" access="public" location="testcpp.h" documented="true" writable="false" brief="This property holds a name">
186187
<getter name="name"/>
187188
</property>
189+
<property name="secondBoolProp" fullname="TestQDoc::TestDerived::secondBoolProp" href="testqdoc-testderived.html#secondBoolProp-prop" status="active" access="public" location="testcpp.h" documented="true" writable="false">
190+
<getter name="secondBoolProp"/>
191+
<notifier name="boolPropChanged"/>
192+
</property>
188193
<property name="someProp" fullname="TestQDoc::TestDerived::someProp" href="testqdoc-testderived.html#someProp-prop" status="active" access="public" location="testcpp.h" documented="true" bindable="true" writable="false">
189194
<getter name="someProp"/>
190195
</property>

src/qdoc/qdoc/tests/validateqdocoutputfiles/testdata/comprehensiveproject/expected/html/test.qhp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@
179179
<keyword name="rear" id="AbstractParent::rear" ref="qml-qdoc-test-abstractparent.html#rear-method"/>
180180
<keyword name="resetBoolProp" id="TestDerived::resetBoolProp" ref="testqdoc-testderived.html#boolProp-prop"/>
181181
<keyword name="sampleReadOnlyProperty" id="TabWidget::sampleReadOnlyProperty" ref="qml-uicomponents-tabwidget.html#sampleReadOnlyProperty-prop"/>
182+
<keyword name="secondBoolProp" id="TestDerived::secondBoolProp" ref="testqdoc-testderived.html#secondBoolProp-prop"/>
183+
<keyword name="secondBoolProp" id="TestDerived::secondBoolProp" ref="testqdoc-testderived.html#secondBoolProp-prop"/>
182184
<keyword name="secondColor" id="ProgressBar::secondColor" ref="qml-uicomponents-progressbar.html#secondColor-prop"/>
183185
<keyword name="setBindableProp" id="TestDerived::setBindableProp" ref="testqdoc-testderived.html#bindableProp-prop"/>
184186
<keyword name="setBoolProp" id="TestDerived::setBoolProp" ref="testqdoc-testderived.html#boolProp-prop"/>

src/qdoc/qdoc/tests/validateqdocoutputfiles/testdata/comprehensiveproject/expected/html/testqdoc-testderived-members.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ <h1 class="title" translate="no">List of All Members for TestDerived</h1>
2828
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-test.html#inlineFunction" translate="no">inlineFunction</a></b></span>()</li>
2929
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-testderived.html#invokeMe" translate="no">invokeMe</a></b></span>() const</li>
3030
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-test.html#methodWithEmDashInItsDocs" translate="no">methodWithEmDashInItsDocs</a></b></span>()</li>
31-
</ul></td><td class="topAlign"><ul>
3231
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-test.html#methodWithEnDashInItsDocs" translate="no">methodWithEnDashInItsDocs</a></b></span>()</li>
32+
</ul></td><td class="topAlign"><ul>
3333
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-testderived.html#name-prop" translate="no">name</a></b></span>() const : const QString *</li>
3434
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-test.html#overload" translate="no">overload</a></b></span>()</li>
3535
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-test.html#overload-1" translate="no">overload</a></b></span>(bool)</li>
3636
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-testderived.html#boolProp-prop" translate="no">resetBoolProp</a></b></span>()</li>
37+
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-testderived.html#secondBoolProp-prop" translate="no">secondBoolProp</a></b></span>() : bool</li>
3738
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-testderived.html#bindableProp-prop" translate="no">setBindableProp</a></b></span>(const QString &amp;)</li>
3839
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-testderived.html#boolProp-prop" translate="no">setBoolProp</a></b></span>(bool)</li>
3940
<li class="fn" translate="no"><span class="name"><b><a href="testqdoc-test.html#someFunction" translate="no">someFunction</a></b></span>(int, int) : int</li>

src/qdoc/qdoc/tests/validateqdocoutputfiles/testdata/comprehensiveproject/expected/html/testqdoc-testderived.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ <h2 id="properties">Properties</h2>
5454
<li class="fn" translate="no"><b><a href="testqdoc-testderived.html#intProp-prop" translate="no">intProp</a></b> : int* const</li>
5555
</ul></td><td class="topAlign"><ul>
5656
<li class="fn" translate="no"><b><a href="testqdoc-testderived.html#name-prop" translate="no">name</a></b> : const QString*</li>
57+
<li class="fn" translate="no"><b><a href="testqdoc-testderived.html#secondBoolProp-prop" translate="no">secondBoolProp</a></b> : const bool</li>
5758
<li class="fn" translate="no"><b><a href="testqdoc-testderived.html#someProp-prop" translate="no">someProp</a></b> : QString</li>
5859
</ul>
5960
</td></tr>
@@ -65,6 +66,7 @@ <h2 id="public-functions">Public Functions</h2>
6566
<tr><td class="memItemLeft rightAlign topAlign"> int *</td><td class="memItemRight bottomAlign"><b><a href="testqdoc-testderived.html#intProp-prop" translate="no">getInt</a></b>()</td></tr>
6667
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-testderived.html#invokeMe" translate="no">invokeMe</a></b>() const</td></tr>
6768
<tr><td class="memItemLeft rightAlign topAlign"> const QString *</td><td class="memItemRight bottomAlign"><b><a href="testqdoc-testderived.html#name-prop" translate="no">name</a></b>() const</td></tr>
69+
<tr><td class="memItemLeft rightAlign topAlign"> bool </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-testderived.html#secondBoolProp-prop" translate="no">secondBoolProp</a></b>()</td></tr>
6870
<tr><td class="memItemLeft rightAlign topAlign"> const QString &amp;</td><td class="memItemRight bottomAlign"><b><a href="testqdoc-testderived.html#someProp-prop" translate="no">someProp</a></b>()</td></tr>
6971
<tr><td class="memItemLeft rightAlign topAlign"> TestQDoc::TestDerived::NotTypedef </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-testderived.html#someValue" translate="no">someValue</a></b>()</td></tr>
7072
</table></div>
@@ -139,6 +141,18 @@ <h3 class="fn" translate="no" id="name-prop"><code class="details extra" transla
139141
<tr><td class="memItemLeft topAlign rightAlign"> const QString *</td><td class="memItemRight bottomAlign"><span class="name"><b>name</b></span>() const</td></tr>
140142
</table></div>
141143
<!-- @@@name -->
144+
<!-- $$$secondBoolProp-prop$$$secondBoolProp$$$boolPropChanged -->
145+
<h3 class="fn" translate="no" id="secondBoolProp-prop"><code class="details extra" translate="no">[read-only]</code> <span class="name">secondBoolProp</span> : const <span class="type">bool</span></h3>
146+
<p>A property sharing a notifier signal with <a href="testqdoc-testderived.html#boolProp-prop" translate="no">boolProp</a>.</p>
147+
<p><b>Access functions:</b></p>
148+
<div class="table"><table class="alignedsummary" translate="no">
149+
<tr><td class="memItemLeft topAlign rightAlign"> bool </td><td class="memItemRight bottomAlign"><span class="name"><b>secondBoolProp</b></span>()</td></tr>
150+
</table></div>
151+
<p><b>Notifier signal:</b></p>
152+
<div class="table"><table class="alignedsummary" translate="no">
153+
<tr><td class="memItemLeft topAlign rightAlign"> void </td><td class="memItemRight bottomAlign"><span class="name"><b><a href="testqdoc-testderived.html#boolProp-prop" translate="no">boolPropChanged</a></b></span>()</td></tr>
154+
</table></div>
155+
<!-- @@@secondBoolProp -->
142156
<!-- $$$someProp-prop$$$someProp -->
143157
<h3 class="fn" translate="no" id="someProp-prop"><code class="details extra" translate="no">[bindable read-only]</code> <span class="name">someProp</span> : <span class="type">QString</span></h3>
144158
<div class="admonition note"><p><b>Note: </b>This property supports <a href="https://wiki.qt.io/QProperty">QProperty</a> bindings.</p>

src/qdoc/qdoc/tests/validateqdocoutputfiles/testdata/comprehensiveproject/expected/html/testtagfile.tags

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,13 @@
291291
<anchor>boolProp-prop</anchor>
292292
<arglist>()</arglist>
293293
</member>
294+
<member kind="function" protection="public" virtualness="non" static="no">
295+
<type>bool</type>
296+
<name>secondBoolProp</name>
297+
<anchorfile>testqdoc-testderived.html</anchorfile>
298+
<anchor>secondBoolProp-prop</anchor>
299+
<arglist>()</arglist>
300+
</member>
294301
<member kind="function" protection="public" virtualness="non" static="no">
295302
<type>const QString &amp;</type>
296303
<name>someProp</name>
@@ -418,6 +425,12 @@
418425
<anchor>name-prop</anchor>
419426
<arglist></arglist>
420427
</member>
428+
<member kind="property" type="bool">
429+
<name>secondBoolProp</name>
430+
<anchorfile>testqdoc-testderived.html</anchorfile>
431+
<anchor>secondBoolProp-prop</anchor>
432+
<arglist></arglist>
433+
</member>
421434
<member kind="property" type="QString">
422435
<name>someProp</name>
423436
<anchorfile>testqdoc-testderived.html</anchorfile>

0 commit comments

Comments
 (0)