Clang: Reparse only if files are changed

Includes are now watched by a file watcher. Unsaved file changes are
watched too. If they are changed the translation units which depend on
them are set to a state which require a reparse. Later the diagnostics
of this units are collected and send back to creator.

Change-Id: I2fb5c7dd6644687f22399edd8d18edd6215c9505
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
Marco Bubke
2015-08-31 12:40:14 +02:00
parent aa6aaee510
commit f2b7371af1
39 changed files with 800 additions and 242 deletions

View File

@@ -30,10 +30,14 @@
#include "translationunits.h"
#include <diagnosticschangedmessage.h>
#include <diagnosticset.h>
#include <projectpartsdonotexistexception.h>
#include <projects.h>
#include <translationunitdoesnotexistexception.h>
#include <QDebug>
namespace ClangBackEnd {
bool operator==(const FileContainer &fileContainer, const TranslationUnit &translationUnit)
@@ -48,15 +52,20 @@ bool operator==(const TranslationUnit &translationUnit, const FileContainer &fil
TranslationUnits::TranslationUnits(ProjectParts &projects, UnsavedFiles &unsavedFiles)
: projects(projects),
unsavedFiles(unsavedFiles)
: fileSystemWatcher(*this),
projectParts(projects),
unsavedFiles_(unsavedFiles)
{
}
void TranslationUnits::createOrUpdate(const QVector<FileContainer> &fileContainers)
{
for (const FileContainer &fileContainer : fileContainers)
for (const FileContainer &fileContainer : fileContainers) {
createOrUpdateTranslationUnit(fileContainer);
updateTranslationUnitsWithChangedDependencies(fileContainer.filePath());
}
sendChangedDiagnostics();
}
static bool removeFromFileContainer(QVector<FileContainer> &fileContainers, const TranslationUnit &translationUnit)
@@ -100,20 +109,78 @@ const TranslationUnit &TranslationUnits::translationUnit(const Utf8String &fileP
return *findIterator;
}
const TranslationUnit &TranslationUnits::translationUnit(const FileContainer &fileContainer) const
{
return translationUnit(fileContainer.filePath(), fileContainer.projectPartId());
}
const std::vector<TranslationUnit> &TranslationUnits::translationUnits() const
{
return translationUnits_;
}
UnsavedFiles &TranslationUnits::unsavedFiles() const
{
return unsavedFiles_;
}
void TranslationUnits::addWatchedFiles(QSet<Utf8String> &filePaths)
{
fileSystemWatcher.addFiles(filePaths);
}
void TranslationUnits::updateTranslationUnitsWithChangedDependencies(const Utf8String &filePath)
{
for (auto &translationUnit : translationUnits_)
translationUnit.updateIsNeedingReparseIfDependencyIsMet(filePath);
}
void TranslationUnits::sendChangedDiagnostics()
{
for (const auto &translationUnit : translationUnits_) {
if (translationUnit.isNeedingReparse())
sendDiagnosticChangedMessage(translationUnit);
}
}
void TranslationUnits::setSendChangeDiagnosticsCallback(std::function<void(const DiagnosticsChangedMessage &)> &&callback)
{
sendDiagnosticsChangedCallback = std::move(callback);
}
QVector<FileContainer> TranslationUnits::newerFileContainers(const QVector<FileContainer> &fileContainers) const
{
QVector<FileContainer> newerContainers;
auto translationUnitIsNewer = [this] (const FileContainer &fileContainer) {
try {
return translationUnit(fileContainer).documentRevision() != fileContainer.documentRevision();
} catch (const TranslationUnitDoesNotExistException &) {
return true;
}
};
std::copy_if(fileContainers.cbegin(),
fileContainers.cend(),
std::back_inserter(newerContainers),
translationUnitIsNewer);
return newerContainers;
}
void TranslationUnits::createOrUpdateTranslationUnit(const FileContainer &fileContainer)
{
TranslationUnit::FileExistsCheck checkIfFileExists = fileContainer.hasUnsavedFileContent() ? TranslationUnit::DoNotCheckIfFileExists : TranslationUnit::CheckIfFileExists;
auto findIterator = findTranslationUnit(fileContainer);
if (findIterator == translationUnits_.end())
if (findIterator == translationUnits_.end()) {
translationUnits_.push_back(TranslationUnit(fileContainer.filePath(),
unsavedFiles,
projects.project(fileContainer.projectPartId()),
projectParts.project(fileContainer.projectPartId()),
*this,
checkIfFileExists));
translationUnits_.back().setDocumentRevision(fileContainer.documentRevision());
} else {
findIterator->setDocumentRevision(fileContainer.documentRevision());
}
}
std::vector<TranslationUnit>::iterator TranslationUnits::findTranslationUnit(const FileContainer &fileContainer)
@@ -129,7 +196,7 @@ std::vector<TranslationUnit>::const_iterator TranslationUnits::findTranslationUn
void TranslationUnits::checkIfProjectPartExists(const Utf8String &projectFileName) const
{
projects.project(projectFileName);
projectParts.project(projectFileName);
}
void TranslationUnits::checkIfProjectPartsExists(const QVector<FileContainer> &fileContainers) const
@@ -137,7 +204,7 @@ void TranslationUnits::checkIfProjectPartsExists(const QVector<FileContainer> &f
Utf8StringVector notExistingProjectParts;
for (const FileContainer &fileContainer : fileContainers) {
if (!projects.hasProjectPart(fileContainer.projectPartId()))
if (!projectParts.hasProjectPart(fileContainer.projectPartId()))
notExistingProjectParts.push_back(fileContainer.projectPartId());
}
@@ -146,5 +213,15 @@ void TranslationUnits::checkIfProjectPartsExists(const QVector<FileContainer> &f
}
void TranslationUnits::sendDiagnosticChangedMessage(const TranslationUnit &translationUnit)
{
if (sendDiagnosticsChangedCallback) {
DiagnosticsChangedMessage message(translationUnit.fileContainer(),
translationUnit.diagnostics().toDiagnosticContainers());
sendDiagnosticsChangedCallback(std::move(message));
}
}
} // namespace ClangBackEnd