summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-07-20 16:55:17 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2022-11-25 17:03:22 +0100
commitd25ee859693fdbcdd18e41a2411b5627ff6261b1 (patch)
tree74e6352e441c767243642b4c3a31e4ea15ea08aa
parent064d5d2a0e2936275ad14e6ebcdbdb20862a3cd8 (diff)
downloadqttools-d25ee859693fdbcdd18e41a2411b5627ff6261b1.tar.gz
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. Pick-to: 6.4 6.2 Change-Id: I33fcc57039acfc667e095e782cdd6eb4f592028b Reviewed-by: Luca Di Sera <luca.disera@qt.io>
-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 b009ac6b7..64389ead9 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -38,7 +38,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>
@@ -166,6 +166,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);
@@ -177,14 +219,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);
}
/*!