summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-07-20 16:55:17 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-11-25 18:27:09 +0000
commit25137909a7430c9b1b0e5f7f0d6dfec3ca5e5843 (patch)
treed432d2693df923fc0e098e75da86160b01f0ad69
parent85ef8291b2ae9e333949468cbb294938fcc6a099 (diff)
qdoc: Cache source files when retrieving code snippets
qdoc often retrieves the contents of a source file and matching headers via the clang cursors when parsing. Cache the last files except the dummy file to avoid reading the same file many times. This avoids roughly 43000 file reads in qtbase. Change-Id: I33fcc57039acfc667e095e782cdd6eb4f592028b Reviewed-by: Luca Di Sera <luca.disera@qt.io> (cherry picked from commit d25ee859693fdbcdd18e41a2411b5627ff6261b1) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qdoc/clangcodeparser.cpp54
1 files changed, 45 insertions, 9 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp
index 0ef9e74d8..67438e115 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -72,7 +72,7 @@ static CXTranslationUnit_Flags flags_ = static_cast<CXTranslationUnit_Flags>(0);
static CXIndex index_ = nullptr;
QByteArray ClangCodeParser::s_fn;
-constexpr const char *fnDummyFileName = "/fn_dummyfile.cpp";
+constexpr const char fnDummyFileName[] = "/fn_dummyfile.cpp";
#ifndef QT_NO_DEBUG_STREAM
template<class T>
@@ -200,6 +200,48 @@ static Access fromCX_CXXAccessSpecifier(CX_CXXAccessSpecifier spec)
/*!
Returns the spelling in the file for a source range
*/
+
+struct FileCacheEntry
+{
+ QByteArray fileName;
+ QByteArray content;
+};
+
+static inline QString fromCache(const QByteArray &cache,
+ unsigned int offset1, unsigned int offset2)
+{
+ return QString::fromUtf8(cache.mid(offset1, offset2 - offset1));
+}
+
+static QString readFile(CXFile cxFile, unsigned int offset1, unsigned int offset2)
+{
+ using FileCache = QList<FileCacheEntry>;
+ static FileCache cache;
+
+ CXString cxFileName = clang_getFileName(cxFile);
+ const QByteArray fileName = clang_getCString(cxFileName);
+ clang_disposeString(cxFileName);
+
+ for (const auto &entry : std::as_const(cache)) {
+ if (fileName == entry.fileName)
+ return fromCache(entry.content, offset1, offset2);
+ }
+
+ // "fn_dummyfile.cpp" comes with varying cxFile values
+ if (fileName == fnDummyFileName)
+ return fromCache(ClangCodeParser::fn(), offset1, offset2);
+
+ QFile file(QString::fromUtf8(fileName));
+ if (file.open(QIODeviceBase::ReadOnly)) { // binary to match clang offsets
+ FileCacheEntry entry{fileName, file.readAll()};
+ cache.prepend(entry);
+ while (cache.size() > 5)
+ cache.removeLast();
+ return fromCache(entry.content, offset1, offset2);
+ }
+ return {};
+}
+
static QString getSpelling(CXSourceRange range)
{
auto start = clang_getRangeStart(range);
@@ -211,14 +253,8 @@ static QString getSpelling(CXSourceRange range)
if (file1 != file2 || offset2 <= offset1)
return QString();
- QFile file(fromCXString(clang_getFileName(file1)));
- 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));
+
+ return readFile(file1, offset1, offset2);
}
/*!