summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTopi Reinio <topi.reinio@qt.io>2020-04-14 15:30:36 +0200
committerTopi Reiniƶ <topi.reinio@qt.io>2020-04-21 06:04:31 +0000
commitd53af222939321fb816d44f86588c3eb8c255e10 (patch)
treec56b5853d743a516a1cb540ba5e8f3218c1eec56
parent8f379adf059977c04c2105b6ca73b04b1a923d8a (diff)
qdoc: Fix handling of default values for function parameters
When using an \fn command to document a function that has default values for parameter(s), The Clang parser retrieves a relevant section of the source file that contains the expression for the default value. In case of \fn, the source is a temporary translation unit that was constructed on the fly - but it may not exist anymore, and the default value is lost. Fix this by storing the contents of the temporary TU for later access. Fixes: QTBUG-83472 Change-Id: I20ad9e3322636450db1def65933837c1c767f2c4 Reviewed-by: Paul Wicking <paul.wicking@qt.io>
-rw-r--r--src/qdoc/clangcodeparser.cpp30
-rw-r--r--src/qdoc/clangcodeparser.h2
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml3
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/html/testqdoc-test.webxml2
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html4
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html4
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html4
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/testcpp.index2
-rw-r--r--tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html4
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp18
-rw-r--r--tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h2
11 files changed, 45 insertions, 30 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp
index db9c2ed07..b5c6a8ac6 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -65,6 +65,9 @@ QT_BEGIN_NAMESPACE
static CXTranslationUnit_Flags flags_ = static_cast<CXTranslationUnit_Flags>(0);
static CXIndex index_ = nullptr;
+QByteArray ClangCodeParser::fn_;
+constexpr const char *fnDummyFileName = "/fn_dummyfile.cpp";
+
#ifndef QT_NO_DEBUG_STREAM
template<class T>
static QDebug operator<<(QDebug debug, const std::vector<T> &v)
@@ -199,11 +202,15 @@ static QString getSpelling(CXSourceRange range)
unsigned int offset1, offset2;
clang_getFileLocation(start, &file1, nullptr, nullptr, &offset1);
clang_getFileLocation(end, &file2, nullptr, nullptr, &offset2);
+
if (file1 != file2 || offset2 <= offset1)
return QString();
QFile file(fromCXString(clang_getFileName(file1)));
- if (!file.open(QFile::ReadOnly))
+ if (!file.open(QFile::ReadOnly)) {
+ if (file.fileName() == fnDummyFileName)
+ return QString::fromUtf8(ClangCodeParser::fn().mid(offset1, offset2 - offset1));
return QString();
+ }
file.seek(offset1);
return QString::fromUtf8(file.read(offset2 - offset1));
}
@@ -1595,6 +1602,7 @@ void ClangCodeParser::parseSourceFile(const Location & /*location*/, const QStri
clang_disposeTranslationUnit(tu);
clang_disposeIndex(index_);
namespaceScope_.clear();
+ fn_.clear();
}
/*!
@@ -1673,17 +1681,17 @@ Node *ClangCodeParser::parseFnArg(const Location &location, const QString &fnArg
args.push_back(pchName_.constData());
}
CXTranslationUnit tu;
- QByteArray fn;
+ fn_.clear();
for (const auto &ns : qAsConst(namespaceScope_))
- fn.prepend("namespace " + ns.toUtf8() + " {");
- fn += fnArg.toUtf8();
- if (!fn.endsWith(";"))
- fn += "{ }";
- fn.append(namespaceScope_.size(), '}');
-
- const char *dummyFileName = "/fn_dummyfile.cpp";
- CXUnsavedFile unsavedFile { dummyFileName, fn.constData(),
- static_cast<unsigned long>(fn.size()) };
+ fn_.prepend("namespace " + ns.toUtf8() + " {");
+ fn_ += fnArg.toUtf8();
+ if (!fn_.endsWith(";"))
+ fn_ += "{ }";
+ fn_.append(namespaceScope_.size(), '}');
+
+ const char *dummyFileName = fnDummyFileName;
+ CXUnsavedFile unsavedFile { dummyFileName, fn_.constData(),
+ static_cast<unsigned long>(fn_.size()) };
CXErrorCode err = clang_parseTranslationUnit2(index, dummyFileName, args.data(), args.size(),
&unsavedFile, 1, flags, &tu);
qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << dummyFileName << args
diff --git a/src/qdoc/clangcodeparser.h b/src/qdoc/clangcodeparser.h
index 9af292e67..1575d31fb 100644
--- a/src/qdoc/clangcodeparser.h
+++ b/src/qdoc/clangcodeparser.h
@@ -62,6 +62,7 @@ public:
void parseSourceFile(const Location &location, const QString &filePath) override;
void precompileHeaders() override;
Node *parseFnArg(const Location &location, const QString &fnArg) override;
+ static const QByteArray &fn() { return fn_; }
private:
void getDefaultArgs();
@@ -79,6 +80,7 @@ private:
std::vector<const char *> args_;
QVector<QByteArray> moreArgs_;
QStringList namespaceScope_;
+ static QByteArray fn_;
};
QT_END_NAMESPACE
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml b/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml
index ad6a4f30f..76025b06e 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml
+++ b/tests/auto/qdoc/generatedoutput/expected_output/docbook/testqdoc-test.xml
@@ -63,13 +63,14 @@
<db:para>An inline function, documented using the \fn QDoc command.</db:para>
</db:section>
<db:section xml:id="someFunction">
-<db:title>Test::int someFunction(int <db:emphasis>v</db:emphasis>)</db:title>
+<db:title>Test::int someFunction(int <db:emphasis>v</db:emphasis> = 0)</db:title>
<db:methodsynopsis>
<db:type>int</db:type>
<db:methodname>someFunction</db:methodname>
<db:methodparam>
<db:type>int</db:type>
<db:parameter>v</db:parameter>
+<db:initializer>0</db:initializer>
</db:methodparam>
<db:synopsisinfo db:role="meta">plain</db:synopsisinfo>
<db:synopsisinfo db:role="signature">int someFunction(int v)</db:synopsisinfo>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/html/testqdoc-test.webxml b/tests/auto/qdoc/generatedoutput/expected_output/html/testqdoc-test.webxml
index d2726cc57..7ae77ec5a 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/html/testqdoc-test.webxml
+++ b/tests/auto/qdoc/generatedoutput/expected_output/html/testqdoc-test.webxml
@@ -39,7 +39,7 @@
<description/>
</function>
<function name="someFunction" fullname="TestQDoc::Test::someFunction" href="testqdoc-test.html#someFunction" status="active" access="public" location="testcpp.h" documented="true" meta="plain" virtual="non" const="false" static="false" final="false" override="false" type="int" signature="int someFunction(int v)">
- <parameter type="int" name="v" default=""/>
+ <parameter type="int" name="v" default="0"/>
<description>
<para>Function that takes a parameter <argument>v</argument>. Also returns the value of <argument>v</argument>.</para>
</description>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html
index 52a10f706..0d4283a8f 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/ignoresince/testqdoc-test.html
@@ -34,7 +34,7 @@
<h2 id="public-functions">Public Functions</h2>
<div class="table"><table class="alignedsummary">
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#inlineFunction">inlineFunction</a></b>()</td></tr>
-<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i>)</td></tr>
+<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i> = 0)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunctionDefaultArg">someFunctionDefaultArg</a></b>(int <i>i</i>, bool <i>b</i> = false)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> virtual void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#virtualFun">virtualFun</a></b>()</td></tr>
</table></div>
@@ -68,7 +68,7 @@
<p>An inline function, documented using the \fn QDoc command.</p>
<!-- @@@inlineFunction -->
<!-- $$$someFunction[overload1]$$$someFunctionint -->
-<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i>)</h3>
+<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i> = 0)</h3>
<p>Function that takes a parameter <i>v</i>. Also returns the value of <i>v</i>.</p>
<p>This function was introduced in Test 1.0.</p>
<!-- @@@someFunction -->
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html
index 3fc1f2bc7..864205274 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html
@@ -40,7 +40,7 @@
<h2 id="public-functions">Public Functions</h2>
<div class="table"><table class="alignedsummary">
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#inlineFunction">inlineFunction</a></b>()</td></tr>
-<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i>)</td></tr>
+<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i> = 0)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunctionDefaultArg">someFunctionDefaultArg</a></b>(int <i>i</i>, bool <i>b</i> = false)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> virtual void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#virtualFun">virtualFun</a></b>()</td></tr>
</table></div>
@@ -85,7 +85,7 @@
<p>An inline function, documented using the \fn QDoc command.</p>
<!-- @@@inlineFunction -->
<!-- $$$someFunction[overload1]$$$someFunctionint -->
-<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i>)</h3>
+<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i> = 0)</h3>
<p>Function that takes a parameter <i>v</i>. Also returns the value of <i>v</i>.</p>
<!-- @@@someFunction -->
<!-- $$$someFunctionDefaultArg[overload1]$$$someFunctionDefaultArgintbool -->
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html
index 4ec52916a..75643dede 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/template/testqdoc-test.html
@@ -34,7 +34,7 @@
<h2 id="public-functions">Public Functions</h2>
<div class="table"><table class="alignedsummary">
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#inlineFunction">inlineFunction</a></b>()</td></tr>
-<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i>)</td></tr>
+<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i> = 0)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunctionDefaultArg">someFunctionDefaultArg</a></b>(int <i>i</i>, bool <i>b</i> = false)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> virtual void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#virtualFun">virtualFun</a></b>()</td></tr>
</table></div>
@@ -73,7 +73,7 @@
<p>An inline function, documented using the \fn QDoc command.</p>
<!-- @@@inlineFunction -->
<!-- $$$someFunction[overload1]$$$someFunctionint -->
-<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i>)</h3>
+<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i> = 0)</h3>
<p>Function that takes a parameter <i>v</i>. Also returns the value of <i>v</i>.</p>
<!-- @@@someFunction -->
<!-- $$$someFunctionDefaultArg[overload1]$$$someFunctionDefaultArgintbool -->
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/testcpp.index b/tests/auto/qdoc/generatedoutput/expected_output/testcpp.index
index ae997fa52..ae3b4a875 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/testcpp.index
+++ b/tests/auto/qdoc/generatedoutput/expected_output/testcpp.index
@@ -22,7 +22,7 @@
<parameter type="bool" name="b" default=""/>
</function>
<function name="someFunction" fullname="TestQDoc::Test::someFunction" href="testqdoc-test.html#someFunction" status="active" access="public" location="testcpp.h" documented="true" meta="plain" virtual="non" const="false" static="false" final="false" override="false" type="int" signature="int someFunction(int v)">
- <parameter type="int" name="v" default=""/>
+ <parameter type="int" name="v" default="0"/>
</function>
<function name="someFunctionDefaultArg" fullname="TestQDoc::Test::someFunctionDefaultArg" href="testqdoc-test.html#someFunctionDefaultArg" status="active" access="public" location="testcpp.h" documented="true" meta="plain" virtual="non" const="false" static="false" final="false" override="false" type="void" signature="void someFunctionDefaultArg(int i, bool b)">
<parameter type="int" name="i" default=""/>
diff --git a/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html
index 84c0c4fe3..49066d0e6 100644
--- a/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html
+++ b/tests/auto/qdoc/generatedoutput/expected_output/testqdoc-test.html
@@ -34,7 +34,7 @@
<h2 id="public-functions">Public Functions</h2>
<div class="table"><table class="alignedsummary">
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#inlineFunction">inlineFunction</a></b>()</td></tr>
-<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i>)</td></tr>
+<tr><td class="memItemLeft rightAlign topAlign"> int </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunction">someFunction</a></b>(int <i>v</i> = 0)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#someFunctionDefaultArg">someFunctionDefaultArg</a></b>(int <i>i</i>, bool <i>b</i> = false)</td></tr>
<tr><td class="memItemLeft rightAlign topAlign"> virtual void </td><td class="memItemRight bottomAlign"><b><a href="testqdoc-test.html#virtualFun">virtualFun</a></b>()</td></tr>
</table></div>
@@ -68,7 +68,7 @@
<p>An inline function, documented using the \fn QDoc command.</p>
<!-- @@@inlineFunction -->
<!-- $$$someFunction[overload1]$$$someFunctionint -->
-<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i>)</h3>
+<h3 class="fn" id="someFunction"><a name="someFunction"></a><span class="type">int</span> Test::<span class="name">someFunction</span>(<span class="type">int</span> <i>v</i> = 0)</h3>
<p>Function that takes a parameter <i>v</i>. Also returns the value of <i>v</i>.</p>
<!-- @@@someFunction -->
<!-- $$$someFunctionDefaultArg[overload1]$$$someFunctionDefaultArgintbool -->
diff --git a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp
index 17045eed5..31b910fae 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp
+++ b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.cpp
@@ -124,13 +124,7 @@ void Test::someFunctionDefaultArg(int i, bool b = false)
return;
}
-/*!
- Function that takes a parameter \a v.
- Also returns the value of \a v.
-\if defined(test_ignoresince)
- \since Test 1.0
-\endif
-*/
+// Documented below with an \fn command. Unnecessary but we support it, and it's used.
int Test::someFunction(int v)
{
return v;
@@ -143,6 +137,16 @@ int Test::someFunction(int v)
*/
/*!
+ \fn int Test::someFunction(int v = 0)
+
+ Function that takes a parameter \a v.
+ Also returns the value of \a v.
+\if defined(test_ignoresince)
+ \since Test 1.0
+\endif
+*/
+
+/*!
Function that must be reimplemented.
*/
void Test::virtualFun()
diff --git a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
index 4ae33a404..cb812375b 100644
--- a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
+++ b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h
@@ -41,7 +41,7 @@ public:
OmittedValue = 99
};
#endif
- int someFunction(int v);
+ int someFunction(int v = 0);
void someFunctionDefaultArg(int i, bool b);
void obsoleteMember();
void anotherObsoleteMember();