diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-07-20 16:55:17 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-11-25 17:03:22 +0100 |
commit | d25ee859693fdbcdd18e41a2411b5627ff6261b1 (patch) | |
tree | 74e6352e441c767243642b4c3a31e4ea15ea08aa | |
parent | 064d5d2a0e2936275ad14e6ebcdbdb20862a3cd8 (diff) | |
download | qttools-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.cpp | 54 |
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); } /*! |