Commit ef28c644 authored by Milian Wolff's avatar Milian Wolff
Browse files

kdev-clang: properly track modification revisions of imported files

The previous code only ever tracked the the modification revision
of a file itself, but not of the files it imported. Now, we actually
do that, which ensures we automatically reparse a file when one of
its imports has changed.
parent e8923578
......@@ -333,9 +333,9 @@ void ClangParseJob::run(ThreadWeaver::JobPointer /*self*/, ThreadWeaver::Thread*
return;
}
auto context = ClangHelpers::buildDUChain(session.mainFile(), imports, session,
minimumFeatures(), includedFiles,
clang()->index(), [this] { return abortRequested(); });
auto context
= ClangHelpers::buildDUChain(session.mainFile(), imports, session, minimumFeatures(), includedFiles,
m_unsavedRevisions, clang()->index(), [this] { return abortRequested(); });
setDuChain(context);
if (abortRequested()) {
......@@ -363,16 +363,6 @@ void ClangParseJob::run(ThreadWeaver::JobPointer /*self*/, ThreadWeaver::Thread*
if (!context) {
continue;
}
{
// prefer the editor modification revision, instead of the on-disk revision
auto it = m_unsavedRevisions.find(context->url());
if (it != m_unsavedRevisions.end()) {
DUChainWriteLocker lock;
auto file = parsingEnvironmentFile(context);
Q_ASSERT(file);
file->setModificationRevision(it.value());
}
}
if (trackerForUrl(context->url())) {
if (clang()->index()->translationUnitForUrl(context->url()) == m_environment.translationUnitUrl()) {
// cache the parse session and the contained translation unit for this chain
......
......@@ -112,7 +112,8 @@ bool importLocationLessThan(const Import& lhs, const Import& rhs)
ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& imports, const ParseSession& session,
TopDUContext::Features features, IncludeFileContexts& includedFiles,
ClangIndex* index, const std::function<bool()>& abortFunction)
const UnsavedRevisions& unsavedRevisions, ClangIndex* index,
const std::function<bool()>& abortFunction)
{
if (includedFiles.contains(file)) {
return {};
......@@ -130,7 +131,7 @@ ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& im
std::sort(sortedImports.begin(), sortedImports.end(), importLocationLessThan);
for (const auto& import : qAsConst(sortedImports)) {
buildDUChain(import.file, imports, session, features, includedFiles, index, abortFunction);
buildDUChain(import.file, imports, session, features, includedFiles, unsavedRevisions, index, abortFunction);
}
const QFileInfo pathInfo(ClangString(clang_getFileName(file)).toString());
......@@ -155,29 +156,31 @@ ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& im
}
includedFiles.insert(file, context);
if (update) {
auto envFile = ClangParsingEnvironmentFile::Ptr(dynamic_cast<ClangParsingEnvironmentFile*>(context->parsingEnvironmentFile().data()));
Q_ASSERT(envFile);
if (!envFile)
return context;
auto envFile = dynamic_cast<ClangParsingEnvironmentFile*>(context->parsingEnvironmentFile().data());
Q_ASSERT(envFile);
if (!envFile)
return context;
if (update) {
/* NOTE: When we are here, then either the translation unit or one of its headers was changed.
* Thus we must always update the translation unit to propagate the change(s).
* See also: https://bugs.kde.org/show_bug.cgi?id=356327
* This assumes that headers are independent, we may need to improve that in the future
* and also update header files more often when other files included therein got updated.
*/
if (path != environment.translationUnitUrl() && !envFile->needsUpdate(&environment) && envFile->featuresSatisfied(features)) {
if (path != environment.translationUnitUrl() && !envFile->needsUpdate(&environment)
&& envFile->featuresSatisfied(features)) {
return context;
} else {
//TODO: don't attempt to update if this environment is worse quality than the outdated one
if (index && envFile->environmentQuality() < environment.quality()) {
index->pinTranslationUnitForUrl(environment.translationUnitUrl(), path);
}
envFile->setEnvironment(environment);
envFile->setModificationRevision(ModificationRevision::revisionForFile(context->url()));
}
// TODO: don't attempt to update if this environment is worse quality than the outdated one
if (index && envFile->environmentQuality() < environment.quality()) {
index->pinTranslationUnitForUrl(environment.translationUnitUrl(), path);
}
envFile->setEnvironment(environment);
envFile->clearModificationRevisions();
context->clearImportedParentContexts();
}
context->setFeatures(features);
......@@ -189,8 +192,17 @@ ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& im
continue;
}
context->addImportedParentContext(ctx, import.location);
envFile->addModificationRevisions(ctx->parsingEnvironmentFile()->allModificationRevisions());
}
context->updateImportsCache();
// prefer the editor modification revision, instead of the on-disk revision
auto it = unsavedRevisions.find(path);
if (it == unsavedRevisions.end()) {
envFile->setModificationRevision(ModificationRevision::revisionForFile(path));
} else {
envFile->setModificationRevision(*it);
}
}
const auto problems = session.problemsForFile(file);
......
......@@ -34,6 +34,11 @@
class ParseSession;
class ClangIndex;
namespace KDevelop
{
class ModificationRevision;
}
struct Import
{
CXFile file;
......@@ -44,6 +49,7 @@ Q_DECLARE_TYPEINFO(Import, Q_MOVABLE_TYPE);
using Imports = QMultiHash<CXFile, Import>;
using IncludeFileContexts = QHash<CXFile, KDevelop::ReferencedTopDUContext>;
using UnsavedRevisions = QHash<KDevelop::IndexedString, KDevelop::ModificationRevision>;
namespace ClangHelpers {
......@@ -75,10 +81,11 @@ KDEVCLANGPRIVATE_EXPORT Imports tuImports(CXTranslationUnit tu);
* The resulting contexts are placed in @a includedFiles.
* @returns the context created for @a file
*/
KDEVCLANGPRIVATE_EXPORT KDevelop::ReferencedTopDUContext buildDUChain(
CXFile file, const Imports& imports, const ParseSession& session,
KDevelop::TopDUContext::Features features, IncludeFileContexts& includedFiles,
ClangIndex* index = nullptr, const std::function<bool()>& abortFunction = {});
KDEVCLANGPRIVATE_EXPORT KDevelop::ReferencedTopDUContext
buildDUChain(CXFile file, const Imports& imports, const ParseSession& session,
KDevelop::TopDUContext::Features features, IncludeFileContexts& includedFiles,
const UnsavedRevisions& unsavedRevisions, ClangIndex* index = nullptr,
const std::function<bool()>& abortFunction = {});
/**
* @return List of possible header extensions used for definition/declaration fallback switching
......
......@@ -57,7 +57,7 @@ ClangPCH::ClangPCH(const ClangParsingEnvironment& environment, ClangIndex* index
}
auto imports = ClangHelpers::tuImports(m_session.unit());
m_context = ClangHelpers::buildDUChain(m_session.mainFile(), imports, m_session, pchFeatures, m_includes);
m_context = ClangHelpers::buildDUChain(m_session.mainFile(), imports, m_session, pchFeatures, m_includes, {});
}
IncludeFileContexts ClangPCH::mapIncludes(CXTranslationUnit tu) const
......
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