diff --git a/languages/clang/clangparsejob.cpp b/languages/clang/clangparsejob.cpp --- a/languages/clang/clangparsejob.cpp +++ b/languages/clang/clangparsejob.cpp @@ -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 @@ } 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)) { diff --git a/languages/clang/codecompletion/context.cpp b/languages/clang/codecompletion/context.cpp --- a/languages/clang/codecompletion/context.cpp +++ b/languages/clang/codecompletion/context.cpp @@ -42,11 +42,14 @@ #include #include #include +#include #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,18 +778,31 @@ qRegisterMetaType(); const QByteArray file = url.toLocalFile().toUtf8(); ParseSession session(m_parseSessionData); + + QVector otherUnsavedFiles; + { + ForegroundLock lock; + otherUnsavedFiles = ClangUtils::unsavedFiles(); + } + QVector allUnsaved; + { const unsigned int completeOptions = clang_defaultCodeCompleteOptions(); CXUnsavedFile unsaved; 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 @@ 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) { diff --git a/languages/clang/duchain/parsesession.cpp b/languages/clang/duchain/parsesession.cpp --- a/languages/clang/duchain/parsesession.cpp +++ b/languages/clang/duchain/parsesession.cpp @@ -183,8 +183,7 @@ : 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 @@ 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; diff --git a/languages/clang/util/clangutils.h b/languages/clang/util/clangutils.h --- a/languages/clang/util/clangutils.h +++ b/languages/clang/util/clangutils.h @@ -29,6 +29,7 @@ #include #include "clangprivateexport.h" +#include "../duchain/unsavedfile.h" namespace ClangUtils { @@ -70,6 +71,16 @@ 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 unsavedFiles(); + + /** * Given a cursor and destination context, returns the string representing the * cursor's scope at its current location. * diff --git a/languages/clang/util/clangutils.cpp b/languages/clang/util/clangutils.cpp --- a/languages/clang/util/clangutils.cpp +++ b/languages/clang/util/clangutils.cpp @@ -24,8 +24,11 @@ #include "../util/clangdebug.h" #include "../util/clangtypes.h" #include "../duchain/cursorkindtraits.h" +#include "../duchain/documentfinderhelpers.h" #include +#include +#include #include @@ -52,6 +55,27 @@ return clang_getCursor(unit, location); } +QVector ClangUtils::unsavedFiles() +{ + QVector 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)"));