logic: Inspect errors during indexing (issue #235)

* Enabled errors table during indexing
* Store intermediate errors in StorageCache
* Open tab for errors if no tab yet
* "Show errors" for file disabled during indexing
* Hide indexing dialogs with ESC instead of stopping indexing
This commit is contained in:
Eberhard Graether
2018-12-06 15:46:42 +01:00
parent 09c6155583
commit b47a0b5b72
21 changed files with 231 additions and 59 deletions
@@ -517,7 +517,17 @@ std::vector<CodeSnippetParams> CodeController::getSnippetsForFileWithState(
params.startLineNumber = 1;
params.refCount = -1;
std::shared_ptr<TextAccess> textAccess = m_storageAccess->getFileContent(filePath);
bool showsErrors = false;
if (m_collection->getSourceLocationFiles().size())
{
std::shared_ptr<SourceLocationFile> file = m_collection->getSourceLocationFiles().begin()->second;
if (file->getSourceLocations().size())
{
showsErrors = (*file->getSourceLocations().begin())->getType() == LOCATION_ERROR;
}
}
std::shared_ptr<TextAccess> textAccess = m_storageAccess->getFileContent(filePath, showsErrors);
params.code = textAccess->getText();
params.modificationTime = m_storageAccess->getFileInfoForFilePath(filePath).lastWriteTime;
@@ -619,7 +629,14 @@ std::vector<CodeSnippetParams> CodeController::getSnippetsForFile(
{
TRACE();
std::shared_ptr<TextAccess> textAccess = m_storageAccess->getFileContent(activeSourceLocations->getFilePath());
bool showsErrors = false;
if (activeSourceLocations->getSourceLocations().size())
{
showsErrors = (*activeSourceLocations->getSourceLocations().begin())->getType() == LOCATION_ERROR;
}
std::shared_ptr<TextAccess> textAccess =
m_storageAccess->getFileContent(activeSourceLocations->getFilePath(), showsErrors);
size_t lineCount = textAccess->getLineCount();
SnippetMerger fileScopedMerger(1, lineCount);
@@ -30,7 +30,7 @@ void ErrorController::errorFilterChanged(const ErrorFilter& filter)
void ErrorController::showError(Id errorId)
{
if (!m_tabShowsErrors[TabId::currentTab()])
if (!m_tabShowsErrors[TabId::currentTab()] || m_newErrorsAdded)
{
errorFilterChanged(getView()->getErrorFilter());
}
@@ -82,6 +82,9 @@ void ErrorController::handleMessage(MessageErrorCountClear* message)
void ErrorController::handleMessage(MessageErrorCountUpdate* message)
{
m_storageAccess->addErrorsToCache(message->newErrors, message->errorCount);
m_newErrorsAdded = true;
ErrorFilter filter = getView()->getErrorFilter();
int room = filter.limit - m_errorCount;
@@ -116,18 +119,21 @@ void ErrorController::handleMessage(MessageErrorCountUpdate* message)
void ErrorController::handleMessage(MessageErrorsAll* message)
{
if (canDisplayErrors())
{
MessageActivateErrors(getView()->getErrorFilter()).dispatch();
}
MessageActivateErrors(getView()->getErrorFilter()).dispatch();
}
void ErrorController::handleMessage(MessageErrorsForFile* message)
{
if (canDisplayErrors())
Project* project = Application::getInstance()->getCurrentProject().get();
if (project && project->isIndexing())
{
MessageActivateErrors(ErrorFilter(), message->file).dispatch();
Application::getInstance()->getDialogView(DialogView::UseCase::GENERAL)->confirm(
"Showing errors for a file is not possible while indexing."
);
return;
}
MessageActivateErrors(ErrorFilter(), message->file).dispatch();
}
void ErrorController::handleMessage(MessageErrorsHelpMessage* message)
@@ -155,16 +161,16 @@ void ErrorController::handleMessage(MessageErrorsHelpMessage* message)
void ErrorController::handleMessage(MessageIndexingFinished* message)
{
m_storageAccess->setUseErrorCache(false);
clear();
showErrors(getView()->getErrorFilter(), false);
getView()->setEnabled(true);
}
void ErrorController::handleMessage(MessageIndexingStarted* message)
{
getView()->setEnabled(false);
m_storageAccess->setUseErrorCache(true);
}
void ErrorController::handleMessage(MessageShowError* message)
@@ -182,6 +188,7 @@ void ErrorController::clear()
m_errorCount = 0;
m_tabShowsErrors.clear();
m_tabActiveFilePath.clear();
m_newErrorsAdded = false;
getView()->clear();
}
@@ -213,17 +220,3 @@ bool ErrorController::showErrors(const ErrorFilter& filter, bool scrollTo)
return errors.size();
}
bool ErrorController::canDisplayErrors() const
{
Project* project = Application::getInstance()->getCurrentProject().get();
if (project && project->isIndexing())
{
Application::getInstance()->getDialogView(DialogView::UseCase::GENERAL)->confirm(
"Errors cannot be activated while indexing."
);
return false;
}
return true;
}
@@ -61,7 +61,6 @@ private:
virtual void clear();
bool showErrors(const ErrorFilter& filter, bool scrollTo);
bool canDisplayErrors() const;
StorageAccess* m_storageAccess;
@@ -69,6 +68,8 @@ private:
std::map<Id, bool> m_tabShowsErrors;
std::map<Id, FilePath> m_tabActiveFilePath;
bool m_newErrorsAdded = false;
};
#endif // ERROR_CONTROLLER_H
@@ -150,6 +150,14 @@ TabsView* TabsController::getView() const
return Controller::getView<TabsView>();
}
void TabsController::handleMessage(MessageActivateErrors* message)
{
if (m_tabs.empty() && Application::getInstance()->isProjectLoaded())
{
MessageTabOpenWith(SearchMatch::createCommand(SearchMatch::COMMAND_ERROR)).dispatch();
}
}
void TabsController::handleMessage(MessageIndexingFinished* message)
{
if (m_tabs.empty() && Application::getInstance()->isProjectLoaded())
@@ -2,6 +2,7 @@
#define TABS_CONTROLLER_H
#include "MessageListener.h"
#include "MessageActivateErrors.h"
#include "MessageIndexingFinished.h"
#include "MessageTabClose.h"
#include "MessageTabOpen.h"
@@ -21,6 +22,7 @@ class ViewLayout;
class TabsController
: public Controller
, public MessageListener<MessageActivateErrors>
, public MessageListener<MessageIndexingFinished>
, public MessageListener<MessageTabClose>
, public MessageListener<MessageTabOpen>
@@ -46,6 +48,7 @@ public:
void onClearTabs();
private:
virtual void handleMessage(MessageActivateErrors* message);
virtual void handleMessage(MessageIndexingFinished* message);
virtual void handleMessage(MessageTabClose* message);
virtual void handleMessage(MessageTabOpen* message);
+20
View File
@@ -27,6 +27,26 @@ struct ErrorFilter
return true;
}
std::vector<ErrorInfo> filterErrors(const std::vector<ErrorInfo>& errors) const
{
std::vector<ErrorInfo> filteredErrors;
for (const ErrorInfo& error : errors)
{
if (filter(error))
{
filteredErrors.push_back(error);
if (limit > 0 && filteredErrors.size() >= limit)
{
break;
}
}
}
return filteredErrors;
}
bool operator==(const ErrorFilter& other) const
{
return error == other.error &&
+4 -1
View File
@@ -73,7 +73,7 @@ public:
virtual std::shared_ptr<SourceLocationFile> getSourceLocationsOfTypeInFile(
const FilePath& filePath, LocationType type) const = 0;
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const = 0;
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath, bool showsErrors) const = 0;
virtual FileInfo getFileInfoForFileId(Id id) const = 0;
@@ -106,6 +106,9 @@ public:
virtual TooltipInfo getTooltipInfoForTokenIds(const std::vector<Id>& tokenIds, TooltipOrigin origin) const = 0;
virtual TooltipInfo getTooltipInfoForSourceLocationIdsAndLocalSymbolIds(
const std::vector<Id>& locationIds, const std::vector<Id>& localSymbolIds) const = 0;
virtual void setUseErrorCache(bool enabled) {}
virtual void addErrorsToCache(const std::vector<ErrorInfo>& newErrors, const ErrorCountInfo& errorCount) {}
};
#endif // STORAGE_ACCESS_H
+1 -1
View File
@@ -93,7 +93,7 @@ DEF_GETTER_1(getSourceLocationsForLocationIds, const std::vector<Id>&, std::shar
DEF_GETTER_1(getSourceLocationsForFile, const FilePath&, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), false, false, false))
DEF_GETTER_3(getSourceLocationsForLinesInFile, const FilePath&, size_t, size_t, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), false, false, false))
DEF_GETTER_2(getSourceLocationsOfTypeInFile, const FilePath&, LocationType, std::shared_ptr<SourceLocationFile>, std::make_shared<SourceLocationFile>(FilePath(), false, false, false))
DEF_GETTER_1(getFileContent, const FilePath&, std::shared_ptr<TextAccess>, nullptr)
DEF_GETTER_2(getFileContent, const FilePath&, bool, std::shared_ptr<TextAccess>, nullptr)
DEF_GETTER_1(getFileInfoForFileId, Id, FileInfo, FileInfo())
DEF_GETTER_1(getFileInfoForFilePath, const FilePath&, FileInfo, FileInfo())
DEF_GETTER_1(getFileInfosForFilePaths, const std::vector<FilePath>&, std::vector<FileInfo>, {})
+1 -1
View File
@@ -54,7 +54,7 @@ public:
std::shared_ptr<SourceLocationFile> getSourceLocationsOfTypeInFile(
const FilePath& filePath, LocationType type) const override;
std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const override;
std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath, bool showsErrors) const override;
FileInfo getFileInfoForFileId(Id id) const override;
+12 -20
View File
@@ -197,6 +197,12 @@ void PersistentStorage::startInjection()
{
m_preInjectionErrorCount = m_sqliteIndexStorage.getErrorCount();
if (!m_preIndexingErrorCountSet)
{
m_preIndexingErrorCount = m_preInjectionErrorCount;
m_preIndexingErrorCountSet = true;
}
m_sqliteIndexStorage.beginTransaction();
}
@@ -208,8 +214,9 @@ void PersistentStorage::finishInjection()
if (m_preInjectionErrorCount < errors.size())
{
ErrorCountInfo errorCount(errors);
errors.erase(errors.begin(), errors.begin() + m_preInjectionErrorCount);
errors.erase(errors.begin(), errors.begin() + m_preInjectionErrorCount - m_preIndexingErrorCount);
MessageErrorCountUpdate(errorCount, errors).dispatch();
m_preIndexingErrorCount = 0;
}
}
@@ -539,7 +546,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getFullTextSearchLo
for (const FullTextSearchResult& fileHits : m_fullTextSearchIndex.searchForTerm(searchTerm))
{
const FilePath filePath = getFileNodePath(fileHits.fileId);
std::shared_ptr<TextAccess> fileContent = getFileContent(filePath);
std::shared_ptr<TextAccess> fileContent = getFileContent(filePath, false);
int charsTotal = 0;
int lineNumber = 1;
@@ -1459,7 +1466,7 @@ std::shared_ptr<SourceLocationFile> PersistentStorage::getSourceLocationsOfTypeI
return m_sqliteIndexStorage.getSourceLocationsOfTypeInFile(filePath, type);
}
std::shared_ptr<TextAccess> PersistentStorage::getFileContent(const FilePath& filePath) const
std::shared_ptr<TextAccess> PersistentStorage::getFileContent(const FilePath& filePath, bool showsErrors) const
{
TRACE();
@@ -1529,22 +1536,7 @@ ErrorCountInfo PersistentStorage::getErrorCount() const
std::vector<ErrorInfo> PersistentStorage::getErrorsLimited(const ErrorFilter& filter) const
{
std::vector<ErrorInfo> errors;
for (const ErrorInfo& error : m_sqliteIndexStorage.getAllErrorInfos())
{
if (filter.filter(error))
{
errors.push_back(error);
if (filter.limit > 0 && errors.size() >= filter.limit)
{
break;
}
}
}
return errors;
return filter.filterErrors(m_sqliteIndexStorage.getAllErrorInfos());
}
std::vector<ErrorInfo> PersistentStorage::getErrorsForFileLimited(const ErrorFilter& filter, const FilePath& filePath) const
@@ -1947,7 +1939,7 @@ TooltipSnippet PersistentStorage::getTooltipSnippetForNode(const StorageNode& no
};
std::vector<Annotation> annotations;
std::vector<std::string> lines = getFileContent(sigLoc->getFilePath())->getLines(
std::vector<std::string> lines = getFileContent(sigLoc->getFilePath(), false)->getLines(
sigLoc->getLineNumber(), sigLoc->getEndLocation()->getLineNumber());
// check if signature location refers to correct locations in the code
+3 -1
View File
@@ -120,7 +120,7 @@ public:
std::shared_ptr<SourceLocationFile> getSourceLocationsOfTypeInFile(
const FilePath& filePath, LocationType type) const override;
std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const override;
std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath, bool showsErrors) const override;
bool hasContentForFile(const FilePath& filePath) const;
FileInfo getFileInfoForFileId(Id id) const override;
@@ -204,6 +204,8 @@ private:
void buildMemberEdgeIdOrderMap();
void buildHierarchyCache();
bool m_preIndexingErrorCountSet = false;
size_t m_preIndexingErrorCount = 0;
size_t m_preInjectionErrorCount = 0;
SearchIndex m_commandIndex;
+94
View File
@@ -1,10 +1,17 @@
#include "StorageCache.h"
#include "SourceLocationCollection.h"
#include "SourceLocationFile.h"
#include "TextAccess.h"
#include "utility.h"
void StorageCache::clear()
{
m_graphForAll.reset();
m_storageStats = StorageStats();
setUseErrorCache(false);
}
std::shared_ptr<Graph> StorageCache::getGraphForAll() const
@@ -26,3 +33,90 @@ StorageStats StorageCache::getStorageStats() const
return m_storageStats;
}
std::shared_ptr<TextAccess> StorageCache::getFileContent(const FilePath& filePath, bool showsErrors) const
{
if (m_useErrorCache && showsErrors)
{
return TextAccess::createFromFile(filePath);
}
return StorageAccessProxy::getFileContent(filePath, showsErrors);
}
ErrorCountInfo StorageCache::getErrorCount() const
{
if (!m_useErrorCache)
{
return StorageAccessProxy::getErrorCount();
}
return m_errorCount;
}
std::vector<ErrorInfo> StorageCache::getErrorsLimited(const ErrorFilter& filter) const
{
if (!m_useErrorCache)
{
return StorageAccessProxy::getErrorsLimited(filter);
}
return filter.filterErrors(m_cachedErrors);
}
std::vector<ErrorInfo> StorageCache::getErrorsForFileLimited(const ErrorFilter& filter, const FilePath& filePath) const
{
if (!m_useErrorCache)
{
return StorageAccessProxy::getErrorsForFileLimited(filter, filePath);
}
return {};
}
std::shared_ptr<SourceLocationCollection> StorageCache::getErrorSourceLocations(const std::vector<ErrorInfo>& errors) const
{
std::shared_ptr<SourceLocationCollection> collection = StorageAccessProxy::getErrorSourceLocations(errors);
if (m_useErrorCache)
{
std::map<std::wstring, bool> fileIndexed;
for (const ErrorInfo& error : m_cachedErrors)
{
fileIndexed.emplace(error.filePath, error.indexed);
}
collection->forEachSourceLocationFile(
[&](std::shared_ptr<SourceLocationFile> file)
{
file->setIsComplete(false);
auto it = fileIndexed.find(file->getFilePath().wstr());
if (it != fileIndexed.end())
{
file->setIsIndexed(it->second);
}
else
{
file->setIsIndexed(true);
}
}
);
}
return collection;
}
void StorageCache::setUseErrorCache(bool enabled)
{
m_useErrorCache = enabled;
m_cachedErrors.clear();
m_errorCount = ErrorCountInfo();
}
void StorageCache::addErrorsToCache(const std::vector<ErrorInfo>& newErrors, const ErrorCountInfo& errorCount)
{
utility::append(m_cachedErrors, newErrors);
m_errorCount = errorCount;
}
+16 -2
View File
@@ -11,13 +11,27 @@ class StorageCache
public:
void clear();
virtual std::shared_ptr<Graph> getGraphForAll() const;
std::shared_ptr<Graph> getGraphForAll() const override;
virtual StorageStats getStorageStats() const;
StorageStats getStorageStats() const override;
std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath, bool showsErrors) const override;
ErrorCountInfo getErrorCount() const override;
std::vector<ErrorInfo> getErrorsLimited(const ErrorFilter& filter) const override;
std::vector<ErrorInfo> getErrorsForFileLimited(const ErrorFilter& filter, const FilePath& filePath) const override;
std::shared_ptr<SourceLocationCollection> getErrorSourceLocations(const std::vector<ErrorInfo>& errors) const override;
void setUseErrorCache(bool enabled) override;
void addErrorsToCache(const std::vector<ErrorInfo>& newErrors, const ErrorCountInfo& errorCount) override;
private:
mutable std::shared_ptr<Graph> m_graphForAll;
mutable StorageStats m_storageStats;
bool m_useErrorCache = false;
ErrorCountInfo m_errorCount;
std::vector<ErrorInfo> m_cachedErrors;
};
#endif // STORAGE_CACHE_H
+1 -1
View File
@@ -219,7 +219,7 @@ bool RefreshInfoGenerator::didFileChange(const FileInfo& info, std::shared_ptr<c
return true;
}
std::shared_ptr<TextAccess> storedFileContent = storage->getFileContent(info.path);
std::shared_ptr<TextAccess> storedFileContent = storage->getFileContent(info.path, false);
std::shared_ptr<TextAccess> diskFileContent = TextAccess::createFromFile(diskFileInfo.path);
const std::vector<std::string>& diskFileLines = diskFileContent->getAllLines();
@@ -4,6 +4,8 @@
#include <QLabel>
#include <QVariant>
#include "Application.h"
#include "Project.h"
#include "ResourcePaths.h"
#include "MessageErrorsForFile.h"
@@ -120,6 +122,12 @@ void QtCodeFileTitleBar::setIsComplete(bool isComplete)
{
m_titleButton->setIsComplete(isComplete);
m_showErrorsButton->setVisible(!isComplete);
Project* project = Application::getInstance()->getCurrentProject().get();
if (project && project->isIndexing())
{
m_showErrorsButton->setVisible(false);
}
}
void QtCodeFileTitleBar::setIsIndexed(bool isIndexed)
-4
View File
@@ -160,8 +160,6 @@ void QtStatusBar::showIndexingProgress(size_t progressPercent)
m_indexingStatus->show();
m_vlineIndexing->show();
m_errorButton.setEnabled(false);
m_indexingProgress->setValue(progressPercent);
}
@@ -169,8 +167,6 @@ void QtStatusBar::hideIndexingProgress()
{
m_indexingStatus->hide();
m_vlineIndexing->hide();
m_errorButton.setEnabled(true);
}
void QtStatusBar::resizeEvent(QResizeEvent* event)
+5
View File
@@ -539,6 +539,11 @@ QtIndexingDialog* QtDialogView::createWindow()
connect(window, &QtIndexingDialog::visibleChanged, this, &QtDialogView::dialogVisibilityChanged);
if (m_mainWindow)
{
connect(m_mainWindow, &QtMainWindow::hideIndexingDialog, window, &QtWindow::handleClosePress);
}
m_windowStack.pushWindow(window);
if (!m_dialogsVisible)
+12 -1
View File
@@ -401,6 +401,17 @@ void QtIndexingDialog::handleNext()
}
void QtIndexingDialog::handleClose()
{
if (m_type == DIALOG_INDEXING || m_type == DIALOG_PROGRESS || m_type == DIALOG_UNKNOWN_PROGRESS)
{
emit visibleChanged(false);
return;
}
QtWindow::handleClose();
}
void QtIndexingDialog::handleCancelPress()
{
if (m_type == DIALOG_INDEXING)
{
@@ -543,7 +554,7 @@ void QtIndexingDialog::addButtons(QBoxLayout* layout)
m_closeButton = new QPushButton("Cancel");
m_closeButton->setObjectName("windowButton");
connect(m_closeButton, &QPushButton::clicked, this, &QtIndexingDialog::handleClosePress);
connect(m_closeButton, &QPushButton::clicked, this, &QtIndexingDialog::handleCancelPress);
QHBoxLayout* buttons = new QHBoxLayout();
buttons->addWidget(m_closeButton);
+3
View File
@@ -61,6 +61,9 @@ protected:
virtual void handleNext() override;
virtual void handleClose() override;
private slots:
void handleCancelPress();
private:
void setType(DialogType type);
+1
View File
@@ -493,6 +493,7 @@ void QtMainWindow::keyPressEvent(QKeyEvent* event)
case Qt::Key_Escape:
emit hideScreenSearch();
emit hideIndexingDialog();
break;
case Qt::Key_Slash:
+1
View File
@@ -90,6 +90,7 @@ public:
signals:
void showScreenSearch();
void hideScreenSearch();
void hideIndexingDialog();
protected:
virtual void showEvent(QShowEvent* event) override;