Commit f14a8fc9 authored by Sven Brauch's avatar Sven Brauch

clang: fix precompiled preamble cache misses

We were a) passing in a wrong file size, and b) a different set of unsaved
files on building the translation unit as compared to invoking completion.
This resulted in the precompiled preamble being rebuilt every single time.
On my test file, time spent in clang_codeCompleteAt goes down from ~700ms
to ~12ms with this change after the project is fully parsed.

It still doesn't work in header files at all.

Differential Revision: https://phabricator.kde.org/D6905
parent 0e6fce28
......@@ -52,6 +52,7 @@
#include "duchain/clangparsingenvironmentfile.h"
#include "util/clangdebug.h"
#include "util/clangtypes.h"
#include "util/clangutils.h"
#include "clangsupport.h"
#include "duchain/documentfinderhelpers.h"
......@@ -191,21 +192,18 @@ ClangParseJob::ClangParseJob(const IndexedString& url, ILanguageSupport* languag
}
m_environment.setProjectPaths(projectPaths);
m_unsavedFiles = ClangUtils::unsavedFiles();
foreach(auto document, ICore::self()->documentController()->openDocuments()) {
auto textDocument = document->textDocument();
// TODO: Introduce a cache so we don't have to re-read all the open documents
// which were not changed since the last run
if (!textDocument || !textDocument->url().isLocalFile()
|| !DocumentFinderHelpers::mimeTypesList().contains(textDocument->mimeType()))
{
if ( !textDocument ) {
continue;
}
m_unsavedFiles << UnsavedFile(textDocument->url().toLocalFile(), textDocument->textLines(textDocument->documentRange()));
const IndexedString indexedUrl(textDocument->url());
m_unsavedRevisions.insert(indexedUrl, ModificationRevision::revisionForFile(indexedUrl));
if (indexedUrl == tuUrl) {
m_tuDocumentIsUnsaved = true;
}
m_unsavedRevisions.insert(indexedUrl, ModificationRevision::revisionForFile(indexedUrl));
}
if (auto tracker = trackerForUrl(url)) {
......
......@@ -42,11 +42,14 @@
#include <language/duchain/types/typeutils.h>
#include <language/codecompletion/codecompletionmodel.h>
#include <language/codecompletion/normaldeclarationcompletionitem.h>
#include <util/foregroundlock.h>
#include "../util/clangdebug.h"
#include "../util/clangtypes.h"
#include "../util/clangutils.h"
#include "../duchain/clangdiagnosticevaluator.h"
#include "../duchain/parsesession.h"
#include "../duchain/duchainutils.h"
#include "../duchain/navigationwidget.h"
#include "../clangsettings/clangsettingsmanager.h"
......@@ -775,6 +778,14 @@ ClangCodeCompletionContext::ClangCodeCompletionContext(const DUContextPointer& c
qRegisterMetaType<MemberAccessReplacer::Type>();
const QByteArray file = url.toLocalFile().toUtf8();
ParseSession session(m_parseSessionData);
QVector<UnsavedFile> otherUnsavedFiles;
{
ForegroundLock lock;
otherUnsavedFiles = ClangUtils::unsavedFiles();
}
QVector<CXUnsavedFile> allUnsaved;
{
const unsigned int completeOptions = clang_defaultCodeCompleteOptions();
......@@ -782,11 +793,16 @@ ClangCodeCompletionContext::ClangCodeCompletionContext(const DUContextPointer& c
unsaved.Filename = file.constData();
const QByteArray content = m_text.toUtf8();
unsaved.Contents = content.constData();
unsaved.Length = content.size() + 1; // + \0-byte
unsaved.Length = content.size();
for ( const auto& f : otherUnsavedFiles ) {
allUnsaved.append(f.toClangApi());
}
allUnsaved.append(unsaved);
m_results.reset(clang_codeCompleteAt(session.unit(), file.constData(),
position.line() + 1, position.column() + 1,
content.isEmpty() ? nullptr : &unsaved, content.isEmpty() ? 0 : 1,
allUnsaved.data(), allUnsaved.size(),
completeOptions));
if (!m_results) {
......@@ -833,11 +849,12 @@ ClangCodeCompletionContext::ClangCodeCompletionContext(const DUContextPointer& c
unsaved.Filename = file.constData();
const QByteArray content = m_text.toUtf8();
unsaved.Contents = content.constData();
unsaved.Length = content.size() + 1;
unsaved.Length = content.size();
allUnsaved[allUnsaved.size() - 1] = unsaved;
m_results.reset(clang_codeCompleteAt(session.unit(), file.constData(),
position.line() + 1, position.column() + 1 + 1,
&unsaved, 1,
allUnsaved.data(), allUnsaved.size(),
clang_defaultCodeCompleteOptions()));
if (m_results && m_results->NumResults) {
......
......@@ -183,8 +183,7 @@ ParseSessionData::ParseSessionData(const QVector<UnsavedFile>& unsavedFiles, Cla
: m_file(nullptr)
, m_unit(nullptr)
{
unsigned int flags = CXTranslationUnit_CXXChainedPCH
| CXTranslationUnit_DetailedPreprocessingRecord
unsigned int flags = CXTranslationUnit_DetailedPreprocessingRecord
#if CINDEX_VERSION_MINOR >= 34
| CXTranslationUnit_KeepGoing
#endif
......@@ -196,6 +195,9 @@ ParseSessionData::ParseSessionData(const QVector<UnsavedFile>& unsavedFiles, Cla
flags |= CXTranslationUnit_ForSerialization;
} else {
flags |= CXTranslationUnit_CacheCompletionResults
#if CINDEX_VERSION_MINOR >= 32
| CXTranslationUnit_CreatePreambleOnFirstParse
#endif
| CXTranslationUnit_PrecompiledPreamble;
if (environment.quality() == ClangParsingEnvironment::Unknown) {
flags |= CXTranslationUnit_Incomplete;
......
......@@ -24,8 +24,11 @@
#include "../util/clangdebug.h"
#include "../util/clangtypes.h"
#include "../duchain/cursorkindtraits.h"
#include "../duchain/documentfinderhelpers.h"
#include <language/duchain/stringhelpers.h>
#include <interfaces/icore.h>
#include <interfaces/idocumentcontroller.h>
#include <clang-c/Index.h>
......@@ -52,6 +55,27 @@ CXCursor ClangUtils::getCXCursor(int line, int column, const CXTranslationUnit&
return clang_getCursor(unit, location);
}
QVector<UnsavedFile> ClangUtils::unsavedFiles()
{
QVector<UnsavedFile> ret;
foreach(auto document, ICore::self()->documentController()->openDocuments()) {
auto textDocument = document->textDocument();
// TODO: Introduce a cache so we don't have to re-read all the open documents
// which were not changed since the last run
if (!textDocument || !textDocument->url().isLocalFile()
|| !DocumentFinderHelpers::mimeTypesList().contains(textDocument->mimeType()))
{
continue;
}
if (!textDocument->isModified()) {
continue;
}
ret << UnsavedFile(textDocument->url().toLocalFile(),
textDocument->textLines(textDocument->documentRange()));
}
return ret;
}
KTextEditor::Range ClangUtils::rangeForIncludePathSpec(const QString& line, const KTextEditor::Range& originalRange)
{
static const QRegularExpression pattern(QStringLiteral("^\\s*(#include|#import)"));
......
......@@ -29,6 +29,7 @@
#include <clang-c/Index.h>
#include "clangprivateexport.h"
#include "../duchain/unsavedfile.h"
namespace ClangUtils
{
......@@ -69,6 +70,16 @@ namespace ClangUtils
*/
bool isScopeKind(CXCursorKind kind);
/**
* @brief Retrieve a list of all unsaved files.
*
* @note Since this reads text from the editor widget, it must be called from the
* GUI thread or with the foreground lock held.
*
* @return vector of all unsaved files and their current contents
*/
KDEVCLANGPRIVATE_EXPORT QVector<UnsavedFile> unsavedFiles();
/**
* Given a cursor and destination context, returns the string representing the
* cursor's scope at its current location.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment