summaryrefslogtreecommitdiff
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 17:57:09 +0000
commite5d66b2a15323e31b418a43628ba4bcd31f193f9 (patch)
tree48b285b552d0b90d908848580dc3af074ced2c91
parent10edc4f59c4d58123785f6c675ef4d3583a01355 (diff)
downloadqttools-e5d66b2a15323e31b418a43628ba4bcd31f193f9.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. 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 c369b1c02..60ce615be 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);
}
/*!