ui/logic/data: refreshing only source files that have been updated
This change adds the refresh component that allows for refreshing the source code via UI or shortcut. If automatic refreshing is activated via the UI, the code is refreshed anytime the window gets focus. The contents of all the updated source files get removed from Storage, before reparsing them. File dependencies are not respected yet.
This commit is contained in:
+1
-1
@@ -45,7 +45,7 @@ set(Boost_USE_MULTITHREAD ON)
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
set(BOOST_LIBRARYDIR $ENV{BOOST_155_DIR})
|
||||
find_package(Boost 1.55 COMPONENTS system filesystem REQUIRED)
|
||||
find_package(Boost 1.55 COMPONENTS system filesystem date_time REQUIRED)
|
||||
|
||||
# Eigen -------------------------------------------------------------------------
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,32 @@
|
||||
#refresh_bar {
|
||||
background: white;
|
||||
}
|
||||
|
||||
QPushButton {
|
||||
background: #E0E0E0;
|
||||
border: none;
|
||||
background-position: 15px 5px;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
QPushButton:hover, QPushButton:checked {
|
||||
background: #B2B2B2;
|
||||
}
|
||||
|
||||
QPushButton#refresh_button {
|
||||
border-bottom-left-radius: 12px;
|
||||
border-top-left-radius: 12px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
QPushButton#auto_refresh_button {
|
||||
border-bottom-right-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
}
|
||||
|
||||
QToolTip {
|
||||
background-color: rgb(204, 204, 204);
|
||||
border: 1px solid rgb(0, 0, 0);
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
@@ -15,7 +15,7 @@ int main()
|
||||
int b = diff(a, 3);
|
||||
int c = a * b;
|
||||
|
||||
// int x = y;
|
||||
int x = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
update
|
||||
@@ -1,4 +1,25 @@
|
||||
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
@@ -31,24 +52,6 @@ SearchMatch.cpp INFO:
|
||||
237 A::A
|
||||
^^^^
|
||||
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Settings.cpp WARNING: File for Settings not found.
|
||||
ConfigManager.cpp ERROR: value Bool is not present in config.
|
||||
ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
@@ -64,7 +67,6 @@ ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
ConfigManager.cpp ERROR: value Float is not present in config.
|
||||
ConfigManager.cpp ERROR: value String is not present in config.
|
||||
ConfigManager.cpp ERROR: value NewBool is not present in config.
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
Storage.cpp INFO: typedef: type -> int <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: class: Class <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:1 1:1>
|
||||
@@ -107,6 +109,17 @@ Storage.cpp INFO: global usage: isTrue -> global <file.cpp 1:7 1:7>
|
||||
Storage.cpp INFO: function: isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: type usage: isTrue -> Struct <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: function: isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: function: isTrue <file.h 1:0 1:0>
|
||||
Storage.cpp INFO: function: main <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: call: main -> isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: function: isTrue <file.h 1:0 1:0>
|
||||
Storage.cpp INFO: function: main <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: call: main -> isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: function: isTrue <file.h 1:0 1:0>
|
||||
Storage.cpp INFO: function: main <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: call: main -> isTrue <file.cpp 1:0 1:0>
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
|
||||
@@ -15,6 +15,8 @@ add_files(
|
||||
qt/element/QtCodeSnippet.h
|
||||
qt/element/QtMainWindow.cpp
|
||||
qt/element/QtMainWindow.h
|
||||
qt/element/QtRefreshBar.cpp
|
||||
qt/element/QtRefreshBar.h
|
||||
qt/element/QtSearchBar.cpp
|
||||
qt/element/QtSearchBar.h
|
||||
qt/element/QtSmartSearchBox.cpp
|
||||
@@ -56,6 +58,8 @@ add_files(
|
||||
qt/view/QtGraphView.h
|
||||
qt/view/QtMainView.cpp
|
||||
qt/view/QtMainView.h
|
||||
qt/view/QtRefreshView.cpp
|
||||
qt/view/QtRefreshView.h
|
||||
qt/view/QtSearchView.cpp
|
||||
qt/view/QtSearchView.h
|
||||
qt/view/QtStatusBarView.cpp
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
#include "utility/messaging/type/MessageSaveProject.h"
|
||||
#include "utility/messaging/type/MessageUndo.h"
|
||||
#include "utility/messaging/type/MessageWindowFocus.h"
|
||||
|
||||
QtMainWindow::QtMainWindow()
|
||||
{
|
||||
@@ -208,6 +209,16 @@ void QtMainWindow::saveLayout()
|
||||
}
|
||||
}
|
||||
|
||||
bool QtMainWindow::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::WindowActivate)
|
||||
{
|
||||
MessageWindowFocus().dispatch();
|
||||
}
|
||||
|
||||
return QMainWindow::event(event);
|
||||
}
|
||||
|
||||
void QtMainWindow::setupProjectMenu()
|
||||
{
|
||||
QMenu *menu = new QMenu(tr("&Project"), this);
|
||||
|
||||
@@ -26,6 +26,9 @@ public:
|
||||
void loadLayout();
|
||||
void saveLayout();
|
||||
|
||||
protected:
|
||||
bool event(QEvent* event);
|
||||
|
||||
public slots:
|
||||
void about();
|
||||
void newProject();
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "qt/element/QtRefreshBar.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "utility/messaging/type/MessageAutoRefreshChanged.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
|
||||
QtRefreshBar::QtRefreshBar()
|
||||
{
|
||||
setObjectName("refresh_bar");
|
||||
|
||||
QBoxLayout* layout = new QHBoxLayout();
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
m_refreshButton = new QPushButton(this);
|
||||
m_refreshButton->setObjectName("refresh_button");
|
||||
m_refreshButton->setToolTip("refresh");
|
||||
m_refreshButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
m_refreshButton->setIcon(QIcon("data/gui/refresh_view/images/refresh.png"));
|
||||
m_refreshButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
||||
layout->addWidget(m_refreshButton);
|
||||
|
||||
m_autoRefreshButton = new QPushButton(this);
|
||||
m_autoRefreshButton->setObjectName("auto_refresh_button");
|
||||
m_autoRefreshButton->setCheckable(true);
|
||||
m_autoRefreshButton->setToolTip("automatic refresh on window focus");
|
||||
m_autoRefreshButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
m_autoRefreshButton->setIcon(QIcon("data/gui/refresh_view/images/auto_refresh.png"));
|
||||
m_autoRefreshButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
||||
layout->addWidget(m_autoRefreshButton);
|
||||
|
||||
connect(m_refreshButton, SIGNAL(clicked()), this, SLOT(refreshClicked()));
|
||||
connect(m_autoRefreshButton, SIGNAL(clicked()), this, SLOT(autoRefreshClicked()));
|
||||
}
|
||||
|
||||
QtRefreshBar::~QtRefreshBar()
|
||||
{
|
||||
}
|
||||
|
||||
QSize QtRefreshBar::sizeHint() const
|
||||
{
|
||||
return QSize(150, 100);
|
||||
}
|
||||
|
||||
void QtRefreshBar::refreshClicked()
|
||||
{
|
||||
MessageRefresh().dispatch();
|
||||
}
|
||||
|
||||
void QtRefreshBar::autoRefreshClicked()
|
||||
{
|
||||
MessageAutoRefreshChanged(m_autoRefreshButton->isChecked()).dispatch();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef QT_REFRESH_BAR_H
|
||||
#define QT_REFRESH_BAR_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class QtRefreshBar
|
||||
: public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtRefreshBar();
|
||||
virtual ~QtRefreshBar();
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
private slots:
|
||||
void refreshClicked();
|
||||
void autoRefreshClicked();
|
||||
|
||||
private:
|
||||
QPushButton* m_refreshButton;
|
||||
QPushButton* m_autoRefreshButton;
|
||||
};
|
||||
|
||||
#endif // QT_REFRESH_BAR_H
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef QT_SEARCH_BOX_H
|
||||
#define QT_SEARCH_BOX_H
|
||||
#ifndef QT_SEARCH_BAR_H
|
||||
#define QT_SEARCH_BAR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -35,4 +35,4 @@ private:
|
||||
// QPushButton* m_caseSensitiveButton;
|
||||
};
|
||||
|
||||
#endif // QT_SEARCH_BOX_H
|
||||
#endif // QT_SEARCH_BAR_H
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "qt/view/QtRefreshView.h"
|
||||
|
||||
#include "component/controller/RefreshController.h"
|
||||
#include "qt/view/QtViewWidgetWrapper.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
|
||||
QtRefreshView::QtRefreshView(ViewLayout* viewLayout)
|
||||
: RefreshView(viewLayout)
|
||||
, m_refreshViewFunctor(std::bind(&QtRefreshView::doRefreshView, this))
|
||||
{
|
||||
m_widget = std::make_shared<QtRefreshBar>();
|
||||
setStyleSheet();
|
||||
}
|
||||
|
||||
QtRefreshView::~QtRefreshView()
|
||||
{
|
||||
}
|
||||
|
||||
void QtRefreshView::createWidgetWrapper()
|
||||
{
|
||||
setWidgetWrapper(std::make_shared<QtViewWidgetWrapper>(m_widget));
|
||||
}
|
||||
|
||||
void QtRefreshView::initView()
|
||||
{
|
||||
}
|
||||
|
||||
void QtRefreshView::refreshView()
|
||||
{
|
||||
m_refreshViewFunctor();
|
||||
}
|
||||
|
||||
void QtRefreshView::doRefreshView()
|
||||
{
|
||||
setStyleSheet();
|
||||
}
|
||||
|
||||
void QtRefreshView::setStyleSheet()
|
||||
{
|
||||
std::string css = TextAccess::createFromFile("data/gui/refresh_view/refresh_view.css")->getText();
|
||||
|
||||
m_widget->setStyleSheet(css.c_str());
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef QT_REFRESH_VIEW_H
|
||||
#define QT_REFRESH_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "component/view/RefreshView.h"
|
||||
#include "qt/element/QtRefreshBar.h"
|
||||
#include "qt/utility/QtThreadedFunctor.h"
|
||||
|
||||
class QtRefreshView
|
||||
: public RefreshView
|
||||
{
|
||||
public:
|
||||
QtRefreshView(ViewLayout* viewLayout);
|
||||
~QtRefreshView();
|
||||
|
||||
// View implementation
|
||||
virtual void createWidgetWrapper();
|
||||
virtual void initView();
|
||||
virtual void refreshView();
|
||||
|
||||
// RefreshView implementation
|
||||
|
||||
private:
|
||||
void doRefreshView();
|
||||
|
||||
void setStyleSheet();
|
||||
|
||||
QtThreadedFunctor<> m_refreshViewFunctor;
|
||||
|
||||
std::shared_ptr<QtRefreshBar> m_widget;
|
||||
};
|
||||
|
||||
# endif // QT_REFRESH_VIEW_H
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "qt/view/QtCodeView.h"
|
||||
#include "qt/view/QtGraphView.h"
|
||||
#include "qt/view/QtMainView.h"
|
||||
#include "qt/view/QtRefreshView.h"
|
||||
#include "qt/view/QtSearchView.h"
|
||||
#include "qt/view/QtStatusBarView.h"
|
||||
#include "qt/view/QtUndoRedoView.h"
|
||||
@@ -30,6 +31,11 @@ std::shared_ptr<GraphView> QtViewFactory::createGraphView(ViewLayout* viewLayout
|
||||
return View::create<QtGraphView>(viewLayout);
|
||||
}
|
||||
|
||||
std::shared_ptr<RefreshView> QtViewFactory::createRefreshView(ViewLayout* viewLayout) const
|
||||
{
|
||||
return View::create<QtRefreshView>(viewLayout);
|
||||
}
|
||||
|
||||
std::shared_ptr<SearchView> QtViewFactory::createSearchView(ViewLayout* viewLayout) const
|
||||
{
|
||||
return View::create<QtSearchView>(viewLayout);
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
virtual std::shared_ptr<MainView> createMainView() const;
|
||||
virtual std::shared_ptr<CodeView> createCodeView(ViewLayout* viewLayout) const;
|
||||
virtual std::shared_ptr<GraphView> createGraphView(ViewLayout* viewLayout) const;
|
||||
virtual std::shared_ptr<RefreshView> createRefreshView(ViewLayout* viewLayout) const;
|
||||
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const;
|
||||
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const;
|
||||
virtual std::shared_ptr<UndoRedoView> createUndoRedoView(ViewLayout* viewLayout) const;
|
||||
|
||||
@@ -46,7 +46,7 @@ void Application::loadProject(const std::string& projectSettingsFilePath)
|
||||
m_project = Project::create(m_graphAccessProxy.get(), m_locationAccessProxy.get());
|
||||
|
||||
m_project->loadProjectSettings(projectSettingsFilePath);
|
||||
m_project->parseCode();
|
||||
m_project->parseCode(false);
|
||||
}
|
||||
|
||||
void Application::loadSource(const std::string& sourceDirectoryPath)
|
||||
@@ -55,13 +55,12 @@ void Application::loadSource(const std::string& sourceDirectoryPath)
|
||||
|
||||
m_project->clearProjectSettings();
|
||||
m_project->setSourceDirectoryPath(sourceDirectoryPath);
|
||||
m_project->parseCode();
|
||||
m_project->parseCode(false);
|
||||
}
|
||||
|
||||
void Application::reloadProject()
|
||||
{
|
||||
m_project->clearStorage();
|
||||
m_project->parseCode();
|
||||
m_project->parseCode(true);
|
||||
}
|
||||
|
||||
void Application::saveProject(const std::string& projectSettingsFilePath)
|
||||
|
||||
@@ -32,6 +32,8 @@ add_files(
|
||||
component/controller/GraphController.h
|
||||
component/controller/GraphLayouter.cpp
|
||||
component/controller/GraphLayouter.h
|
||||
component/controller/RefreshController.cpp
|
||||
component/controller/RefreshController.h
|
||||
component/controller/SearchController.cpp
|
||||
component/controller/SearchController.h
|
||||
component/controller/StatusBarController.cpp
|
||||
@@ -50,6 +52,8 @@ add_files(
|
||||
component/view/GraphView.h
|
||||
component/view/MainView.cpp
|
||||
component/view/MainView.h
|
||||
component/view/RefreshView.cpp
|
||||
component/view/RefreshView.h
|
||||
component/view/SearchView.cpp
|
||||
component/view/SearchView.h
|
||||
component/view/StatusBarView.cpp
|
||||
@@ -204,6 +208,7 @@ add_files(
|
||||
|
||||
utility/messaging/type/MessageActivateTokenLocation.h
|
||||
utility/messaging/type/MessageActivateTokens.h
|
||||
utility/messaging/type/MessageAutoRefreshChanged.h
|
||||
utility/messaging/type/MessageError.h
|
||||
utility/messaging/type/MessageFind.h
|
||||
utility/messaging/type/MessageFinishedParsing.h
|
||||
@@ -219,6 +224,7 @@ add_files(
|
||||
utility/messaging/type/MessageStatus.h
|
||||
utility/messaging/type/MessageRedo.h
|
||||
utility/messaging/type/MessageUndo.h
|
||||
utility/messaging/type/MessageWindowFocus.h
|
||||
|
||||
utility/messaging/Message.h
|
||||
utility/messaging/MessageBase.h
|
||||
|
||||
+26
-4
@@ -77,7 +77,7 @@ void Project::clearStorage()
|
||||
Token::resetNextId();
|
||||
}
|
||||
|
||||
void Project::parseCode()
|
||||
void Project::parseCode(bool refresh)
|
||||
{
|
||||
std::string sourcePath = ProjectSettings::getInstance()->getSourcePath();
|
||||
if (sourcePath.size())
|
||||
@@ -92,11 +92,33 @@ void Project::parseCode()
|
||||
std::vector<std::string> headerSearchPaths = ProjectSettings::getInstance()->getHeaderSearchPaths();
|
||||
headerSearchPaths.push_back(sourcePath);
|
||||
|
||||
CxxParser parser(m_storage.get());
|
||||
std::vector<std::string> filePaths;
|
||||
if (refresh)
|
||||
{
|
||||
filePaths = FileSystem::getFileNamesFromDirectoryUpdatedAfter(sourcePath, extensions, m_lastParseTimeString);
|
||||
}
|
||||
else
|
||||
{
|
||||
filePaths = FileSystem::getFileNamesFromDirectory(sourcePath, extensions);
|
||||
}
|
||||
|
||||
if (!filePaths.size())
|
||||
{
|
||||
MessageFinishedParsing(0, 0, m_storage->getErrorCount()).dispatch();
|
||||
return;
|
||||
}
|
||||
|
||||
m_lastParseTimeString = FileSystem::getTimeStringNow();
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
m_storage->clearFileData(filePaths);
|
||||
}
|
||||
|
||||
CxxParser parser(m_storage.get());
|
||||
clock_t time = clock();
|
||||
parser.parseFiles(
|
||||
FileSystem::getSourceFilesFromDirectory(sourcePath, extensions),
|
||||
filePaths,
|
||||
ApplicationSettings::getInstance()->getHeaderSearchPaths(),
|
||||
headerSearchPaths
|
||||
);
|
||||
@@ -108,7 +130,7 @@ void Project::parseCode()
|
||||
double parseTime = (double)(time) / CLOCKS_PER_SEC;
|
||||
LOG_INFO_STREAM(<< "parse time: " << parseTime);
|
||||
|
||||
MessageFinishedParsing(parseTime, m_storage->getErrorCount()).dispatch();
|
||||
MessageFinishedParsing(filePaths.size(), parseTime, m_storage->getErrorCount()).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -23,7 +23,7 @@ public:
|
||||
bool setSourceDirectoryPath(const std::string& sourceDirectoryPath);
|
||||
|
||||
void clearStorage();
|
||||
void parseCode();
|
||||
void parseCode(bool refresh);
|
||||
|
||||
private:
|
||||
Project(GraphAccessProxy* graphAccessProxy, LocationAccessProxy* locationAccessProxy);
|
||||
@@ -36,6 +36,8 @@ private:
|
||||
LocationAccessProxy* const m_locationAccessProxy;
|
||||
|
||||
std::shared_ptr<Storage> m_storage;
|
||||
|
||||
std::string m_lastParseTimeString;
|
||||
};
|
||||
|
||||
#endif // PROJECT_H
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#include "component/Component.h"
|
||||
#include "component/controller/CodeController.h"
|
||||
#include "component/controller/GraphController.h"
|
||||
#include "component/controller/RefreshController.h"
|
||||
#include "component/controller/SearchController.h"
|
||||
#include "component/controller/StatusBarController.h"
|
||||
#include "component/controller/UndoRedoController.h"
|
||||
#include "component/view/CodeView.h"
|
||||
#include "component/view/GraphView.h"
|
||||
#include "component/view/RefreshView.h"
|
||||
#include "component/view/SearchView.h"
|
||||
#include "component/view/StatusBarView.h"
|
||||
#include "component/view/UndoRedoView.h"
|
||||
@@ -47,6 +49,15 @@ std::shared_ptr<Component> ComponentFactory::createGraphComponent()
|
||||
return component;
|
||||
}
|
||||
|
||||
std::shared_ptr<Component> ComponentFactory::createRefreshComponent()
|
||||
{
|
||||
std::shared_ptr<View> view = m_viewFactory->createRefreshView(m_viewLayout);
|
||||
std::shared_ptr<RefreshController> controller = std::make_shared<RefreshController>();
|
||||
|
||||
std::shared_ptr<Component> component = std::make_shared<Component>(view, controller);
|
||||
return component;
|
||||
}
|
||||
|
||||
std::shared_ptr<Component> ComponentFactory::createSearchComponent()
|
||||
{
|
||||
std::shared_ptr<SearchView> view = m_viewFactory->createSearchView(m_viewLayout);
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
|
||||
std::shared_ptr<Component> createCodeComponent();
|
||||
std::shared_ptr<Component> createGraphComponent();
|
||||
std::shared_ptr<Component> createRefreshComponent();
|
||||
std::shared_ptr<Component> createSearchComponent();
|
||||
std::shared_ptr<Component> createStatusBarComponent();
|
||||
std::shared_ptr<Component> createUndoRedoComponent();
|
||||
|
||||
@@ -24,14 +24,17 @@ void ComponentManager::setup()
|
||||
std::shared_ptr<Component> codeComponent = m_componentFactory->createCodeComponent();
|
||||
m_components.push_back(codeComponent);
|
||||
|
||||
std::shared_ptr<Component> undoRedoComponent = m_componentFactory->createUndoRedoComponent();
|
||||
m_components.push_back(undoRedoComponent);
|
||||
|
||||
std::shared_ptr<Component> refreshComponent = m_componentFactory->createRefreshComponent();
|
||||
m_components.push_back(refreshComponent);
|
||||
|
||||
std::shared_ptr<Component> searchComponent = m_componentFactory->createSearchComponent();
|
||||
m_components.push_back(searchComponent);
|
||||
|
||||
std::shared_ptr<Component> statusBarComponent = m_componentFactory->createStatusBarComponent();
|
||||
m_components.push_back(statusBarComponent);
|
||||
|
||||
std::shared_ptr<Component> undoRedoComponent = m_componentFactory->createUndoRedoComponent();
|
||||
m_components.push_back(undoRedoComponent);
|
||||
}
|
||||
|
||||
ComponentManager::ComponentManager()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "component/controller/RefreshController.h"
|
||||
|
||||
#include "component/view/RefreshView.h"
|
||||
|
||||
RefreshController::RefreshController()
|
||||
: m_autoRefreshEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
RefreshController::~RefreshController()
|
||||
{
|
||||
}
|
||||
|
||||
void RefreshController::handleMessage(MessageAutoRefreshChanged* message)
|
||||
{
|
||||
m_autoRefreshEnabled = message->enabled;
|
||||
}
|
||||
|
||||
void RefreshController::handleMessage(MessageRefresh* message)
|
||||
{
|
||||
getView()->refreshView();
|
||||
}
|
||||
|
||||
void RefreshController::handleMessage(MessageWindowFocus* message)
|
||||
{
|
||||
if (m_autoRefreshEnabled)
|
||||
{
|
||||
MessageRefresh().dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
RefreshView* RefreshController::getView()
|
||||
{
|
||||
return Controller::getView<RefreshView>();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef REFRESH_CONTROLLER_H
|
||||
#define REFRESH_CONTROLLER_H
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageAutoRefreshChanged.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
#include "utility/messaging/type/MessageWindowFocus.h"
|
||||
|
||||
class RefreshView;
|
||||
|
||||
class RefreshController
|
||||
: public Controller
|
||||
, public MessageListener<MessageAutoRefreshChanged>
|
||||
, public MessageListener<MessageRefresh>
|
||||
, public MessageListener<MessageWindowFocus>
|
||||
{
|
||||
public:
|
||||
RefreshController();
|
||||
virtual ~RefreshController();
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageAutoRefreshChanged* message);
|
||||
virtual void handleMessage(MessageRefresh* message);
|
||||
virtual void handleMessage(MessageWindowFocus* message);
|
||||
|
||||
RefreshView* getView();
|
||||
|
||||
bool m_autoRefreshEnabled;
|
||||
};
|
||||
|
||||
#endif // REFRESH_CONTROLLER_H
|
||||
@@ -28,6 +28,7 @@ void StatusBarController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Parsing Finished: ";
|
||||
ss << message->fileCount << " files, ";
|
||||
ss << std::setprecision(2) << message->parseTime << " seconds, ";
|
||||
ss << message->errorCount << " error(s)";
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "component/view/RefreshView.h"
|
||||
|
||||
#include "component/controller/RefreshController.h"
|
||||
|
||||
RefreshView::RefreshView(ViewLayout* viewLayout)
|
||||
: View(viewLayout, Vec2i(100, 100))
|
||||
{
|
||||
}
|
||||
|
||||
RefreshView::~RefreshView()
|
||||
{
|
||||
}
|
||||
|
||||
std::string RefreshView::getName() const
|
||||
{
|
||||
return "RefreshView";
|
||||
}
|
||||
|
||||
RefreshController* RefreshView::getController()
|
||||
{
|
||||
return View::getController<RefreshController>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef REFRESH_VIEW_H
|
||||
#define REFRESH_VIEW_H
|
||||
|
||||
#include "component/view/View.h"
|
||||
|
||||
class RefreshController;
|
||||
|
||||
class RefreshView
|
||||
: public View
|
||||
{
|
||||
public:
|
||||
RefreshView(ViewLayout* viewLayout);
|
||||
virtual ~RefreshView();
|
||||
|
||||
virtual std::string getName() const;
|
||||
|
||||
private:
|
||||
RefreshController* getController();
|
||||
};
|
||||
|
||||
#endif // REFRESH_VIEW_H
|
||||
@@ -6,6 +6,7 @@
|
||||
class CodeView;
|
||||
class GraphView;
|
||||
class MainView;
|
||||
class RefreshView;
|
||||
class SearchView;
|
||||
class StatusBarView;
|
||||
class UndoRedoView;
|
||||
@@ -20,6 +21,7 @@ public:
|
||||
virtual std::shared_ptr<MainView> createMainView() const = 0;
|
||||
virtual std::shared_ptr<CodeView> createCodeView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<GraphView> createGraphView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<RefreshView> createRefreshView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const = 0;
|
||||
virtual std::shared_ptr<UndoRedoView> createUndoRedoView(ViewLayout* viewLayout) const = 0;
|
||||
|
||||
+105
-10
@@ -1,7 +1,5 @@
|
||||
#include "data/Storage.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
@@ -38,6 +36,66 @@ void Storage::clear()
|
||||
m_graph.clear();
|
||||
m_locationCollection.clear();
|
||||
m_tokenIndex.clear();
|
||||
|
||||
m_errorMessages.clear();
|
||||
m_errorLocationCollection.clear();
|
||||
}
|
||||
|
||||
void Storage::clearFileData(const std::vector<std::string>& filePaths)
|
||||
{
|
||||
for (const std::string& filePath : filePaths)
|
||||
{
|
||||
TokenLocationFile* errorFile = m_errorLocationCollection.findTokenLocationFileByPath(filePath);
|
||||
if (errorFile)
|
||||
{
|
||||
m_errorLocationCollection.removeTokenLocationFile(errorFile);
|
||||
}
|
||||
|
||||
TokenLocationFile* file = m_locationCollection.findTokenLocationFileByPath(filePath);
|
||||
if (!file)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
file->forEachTokenLocation(
|
||||
[&](TokenLocation* location)
|
||||
{
|
||||
if (location->isEndTokenLocation())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Token* token = m_graph.getTokenById(location->getTokenId());
|
||||
if (!token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
token->removeLocationId(location->getId());
|
||||
if (token->getLocationIds().size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (token->isEdge())
|
||||
{
|
||||
Edge* edge = dynamic_cast<Edge*>(token);
|
||||
Node* from = edge->getFrom();
|
||||
Node* to = edge->getTo();
|
||||
|
||||
m_graph.removeEdge(edge);
|
||||
removeNodeIfUnreferenced(from);
|
||||
removeNodeIfUnreferenced(to);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeNodeIfUnreferenced(dynamic_cast<Node*>(token));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
m_locationCollection.removeTokenLocationFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
void Storage::logGraph() const
|
||||
@@ -52,7 +110,7 @@ void Storage::logLocations() const
|
||||
|
||||
size_t Storage::getErrorCount() const
|
||||
{
|
||||
return m_errorMessages.size();
|
||||
return m_errorLocationCollection.getTokenLocationCount();
|
||||
}
|
||||
|
||||
void Storage::onError(const ParseLocation& location, const std::string& message)
|
||||
@@ -64,15 +122,38 @@ void Storage::onError(const ParseLocation& location, const std::string& message)
|
||||
return;
|
||||
}
|
||||
|
||||
Id errorId = m_errorMessages.size();
|
||||
bool duplicate = false;
|
||||
std::string filePath = location.filePath;
|
||||
TokenLocationFile* file = m_errorLocationCollection.findTokenLocationFileByPath(filePath);
|
||||
|
||||
TokenLocation* loc = m_errorLocationCollection.addTokenLocation(
|
||||
errorId, location.filePath,
|
||||
location.startLineNumber, location.startColumnNumber,
|
||||
location.endLineNumber, location.endColumnNumber
|
||||
);
|
||||
if (file)
|
||||
{
|
||||
file->forEachTokenLocation(
|
||||
[&](TokenLocation* loc)
|
||||
{
|
||||
if (loc->isStartTokenLocation() &&
|
||||
loc->getLineNumber() == location.startLineNumber &&
|
||||
loc->getColumnNumber() == location.startColumnNumber &&
|
||||
m_errorMessages[loc->getTokenId()] == message)
|
||||
{
|
||||
duplicate = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
m_errorMessages.push_back(message);
|
||||
if (!duplicate)
|
||||
{
|
||||
Id errorId = m_errorMessages.size();
|
||||
|
||||
TokenLocation* loc = m_errorLocationCollection.addTokenLocation(
|
||||
errorId, filePath,
|
||||
location.startLineNumber, location.startColumnNumber,
|
||||
location.endLineNumber, location.endColumnNumber
|
||||
);
|
||||
|
||||
m_errorMessages.push_back(message);
|
||||
}
|
||||
}
|
||||
|
||||
Id Storage::onTypedefParsed(
|
||||
@@ -1030,6 +1111,20 @@ bool Storage::getSubQuerySearchResults(
|
||||
return true;
|
||||
}
|
||||
|
||||
void Storage::removeNodeIfUnreferenced(Node* node)
|
||||
{
|
||||
Id tokenId = node->getId();
|
||||
SearchNode* searchNode = m_tokenIndex.getNode(node->getTokenComponentName()->getSearchNode());
|
||||
|
||||
bool removed = m_graph.removeNodeIfUnreferencedRecursive(node);
|
||||
|
||||
if (removed && searchNode)
|
||||
{
|
||||
searchNode->removeTokenId(tokenId);
|
||||
m_tokenIndex.removeNodeIfUnreferencedRecursive(searchNode);
|
||||
}
|
||||
}
|
||||
|
||||
void Storage::log(std::string type, std::string str, const ParseLocation& location) const
|
||||
{
|
||||
LOG_INFO_STREAM(
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
virtual ~Storage();
|
||||
|
||||
void clear();
|
||||
void clearFileData(const std::vector<std::string>& filePaths);
|
||||
|
||||
void logGraph() const;
|
||||
void logLocations() const;
|
||||
@@ -125,7 +126,6 @@ protected:
|
||||
const SearchIndex& getSearchIndex() const;
|
||||
|
||||
private:
|
||||
|
||||
Node* addNodeHierarchy(Node::NodeType type, std::vector<std::string> nameHierarchy);
|
||||
Node* addNodeHierarchyWithDistinctSignature(Node::NodeType type, const ParseFunction& function);
|
||||
|
||||
@@ -141,6 +141,8 @@ private:
|
||||
bool getSubQuerySearchResults(
|
||||
const std::string& query, const std::string& word, SearchResults* results) const;
|
||||
|
||||
void removeNodeIfUnreferenced(Node* node);
|
||||
|
||||
void log(std::string type, std::string str, const ParseLocation& location) const;
|
||||
|
||||
StorageGraph m_graph;
|
||||
|
||||
@@ -114,13 +114,16 @@ void Graph::removeNode(Node* node)
|
||||
return;
|
||||
}
|
||||
|
||||
node->forEachEdgeOfType(Edge::EDGE_MEMBER, [this, node](Edge* e)
|
||||
{
|
||||
if (node == e->getFrom())
|
||||
node->forEachEdgeOfType(
|
||||
Edge::EDGE_MEMBER,
|
||||
[this, node](Edge* e)
|
||||
{
|
||||
this->removeNode(e->getTo());
|
||||
if (node == e->getFrom())
|
||||
{
|
||||
this->removeNode(e->getTo());
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
node->forEachEdge(
|
||||
[this](Edge* e)
|
||||
@@ -131,7 +134,7 @@ void Graph::removeNode(Node* node)
|
||||
|
||||
if (node->getEdges().size())
|
||||
{
|
||||
LOG_ERROR("Node has still edges.");
|
||||
LOG_ERROR("Node still has edges.");
|
||||
}
|
||||
|
||||
m_nodes.erase(it);
|
||||
@@ -154,6 +157,25 @@ void Graph::removeEdge(Edge* edge)
|
||||
m_edges.erase(it);
|
||||
}
|
||||
|
||||
bool Graph::removeNodeIfUnreferencedRecursive(Node* node)
|
||||
{
|
||||
if (!node->hasReferences())
|
||||
{
|
||||
Node* parent = node->getParentNode();
|
||||
|
||||
removeNode(node);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
removeNodeIfUnreferencedRecursive(parent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* Graph::findNode(std::function<bool(Node*)> func) const
|
||||
{
|
||||
std::map<Id, std::shared_ptr<Node>>::const_iterator it = find_if(m_nodes.begin(), m_nodes.end(),
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
|
||||
void removeNode(Node* node);
|
||||
void removeEdge(Edge* edge);
|
||||
bool removeNodeIfUnreferencedRecursive(Node* node);
|
||||
|
||||
Node* findNode(std::function<bool(Node*)> func) const;
|
||||
Edge* findEdge(std::function<bool(Edge*)> func) const;
|
||||
|
||||
@@ -203,6 +203,37 @@ void Node::forEachChildNode(std::function<void(Node*)> func) const
|
||||
);
|
||||
}
|
||||
|
||||
bool Node::hasReferences() const
|
||||
{
|
||||
if (getLocationIds().size() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasChildrenWithReferences = false;
|
||||
size_t childNodeCount = 0;
|
||||
|
||||
forEachEdgeOfType(
|
||||
Edge::EDGE_MEMBER,
|
||||
[&](Edge* edge)
|
||||
{
|
||||
childNodeCount++;
|
||||
|
||||
if (!hasChildrenWithReferences && edge->getTo() != this && edge->getTo()->hasReferences())
|
||||
{
|
||||
hasChildrenWithReferences = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (hasChildrenWithReferences || getEdges().size() > childNodeCount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Node::isNode() const
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -68,6 +68,8 @@ public:
|
||||
void forEachEdgeOfType(Edge::EdgeType type, std::function<void(Edge*)> func) const;
|
||||
void forEachChildNode(std::function<void(Node*)> func) const;
|
||||
|
||||
bool hasReferences() const;
|
||||
|
||||
// Token implementation.
|
||||
virtual bool isNode() const;
|
||||
virtual bool isEdge() const;
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include "data/location/TokenLocationCollection.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "utility/FileSystem.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "data/location/TokenLocationLine.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
TokenLocationCollection::TokenLocationCollection()
|
||||
{
|
||||
@@ -85,7 +89,13 @@ TokenLocation* TokenLocationCollection::findTokenLocationById(Id id) const
|
||||
|
||||
TokenLocationFile* TokenLocationCollection::findTokenLocationFileByPath(const std::string& filePath) const
|
||||
{
|
||||
std::map<std::string, std::shared_ptr<TokenLocationFile> >::const_iterator it = m_files.find(filePath);
|
||||
std::map<std::string, std::shared_ptr<TokenLocationFile>>::const_iterator it =
|
||||
find_if(m_files.begin(), m_files.end(),
|
||||
[&](const std::pair<std::string, std::shared_ptr<TokenLocationFile>>& p)
|
||||
{
|
||||
return FileSystem::equivalent(p.first, filePath);
|
||||
}
|
||||
);
|
||||
|
||||
if (it != m_files.end())
|
||||
{
|
||||
@@ -119,6 +129,18 @@ void TokenLocationCollection::forEachTokenLocation(std::function<void(TokenLocat
|
||||
}
|
||||
}
|
||||
|
||||
void TokenLocationCollection::removeTokenLocationFile(TokenLocationFile* file)
|
||||
{
|
||||
file->forEachTokenLocation(
|
||||
[&](TokenLocation* location)
|
||||
{
|
||||
m_locations.erase(location->getId());
|
||||
}
|
||||
);
|
||||
|
||||
m_files.erase(file->getFilePath());
|
||||
}
|
||||
|
||||
TokenLocation* TokenLocationCollection::addTokenLocationAsPlainCopy(const TokenLocation* location)
|
||||
{
|
||||
const std::string& filePath = location->getTokenLocationLine()->getTokenLocationFile()->getFilePath();
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
void forEachTokenLocationLine(std::function<void(TokenLocationLine*)> func) const;
|
||||
void forEachTokenLocation(std::function<void(TokenLocation*)> func) const;
|
||||
|
||||
void removeTokenLocationFile(TokenLocationFile* file);
|
||||
|
||||
TokenLocation* addTokenLocationAsPlainCopy(const TokenLocation* location);
|
||||
|
||||
void clear();
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
#include "data/search/SearchMatch.h"
|
||||
|
||||
std::vector<SearchMatch> SearchIndex::getMatches(
|
||||
@@ -34,6 +36,11 @@ void SearchIndex::clear()
|
||||
m_root.m_nodes.clear();
|
||||
}
|
||||
|
||||
size_t SearchIndex::getNodeCount() const
|
||||
{
|
||||
return m_root.getNodeCount() - 1;
|
||||
}
|
||||
|
||||
Id SearchIndex::getWordId(const std::string& word)
|
||||
{
|
||||
return m_dictionary.getWordId(word);
|
||||
@@ -71,6 +78,50 @@ SearchNode* SearchIndex::getNode(const std::string& fullName) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SearchNode* SearchIndex::getNode(const SearchNode* searchNode) const
|
||||
{
|
||||
std::deque<Id> nameIds = searchNode->getNameIdsRecursive();
|
||||
|
||||
if (nameIds.size())
|
||||
{
|
||||
return m_root.getNodeRecursive(&nameIds).get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SearchIndex::removeNode(SearchNode* searchNode)
|
||||
{
|
||||
SearchNode* parent = searchNode->getParent();
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
LOG_ERROR_STREAM(<< "SearchNode to be removed has no parent: " << searchNode->getFullName());
|
||||
return;
|
||||
}
|
||||
|
||||
parent->removeSearchNode(searchNode);
|
||||
}
|
||||
|
||||
bool SearchIndex::removeNodeIfUnreferencedRecursive(SearchNode* searchNode)
|
||||
{
|
||||
if (!searchNode->hasTokenIdsRecursive())
|
||||
{
|
||||
SearchNode* parent = searchNode->getParent();
|
||||
|
||||
removeNode(searchNode);
|
||||
|
||||
if (parent && parent != &m_root)
|
||||
{
|
||||
removeNodeIfUnreferencedRecursive(parent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SearchResults SearchIndex::runFuzzySearch(const std::string& query) const
|
||||
{
|
||||
return m_root.runFuzzySearch(query);
|
||||
|
||||
@@ -20,11 +20,17 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
size_t getNodeCount() const;
|
||||
|
||||
Id getWordId(const std::string& word);
|
||||
const std::string& getWord(Id wordId) const;
|
||||
|
||||
SearchNode* addNode(std::vector<std::string> nameHierarchy);
|
||||
SearchNode* getNode(const std::string& fullName) const;
|
||||
SearchNode* getNode(const SearchNode* searchNode) const;
|
||||
|
||||
void removeNode(SearchNode* searchNode);
|
||||
bool removeNodeIfUnreferencedRecursive(SearchNode* searchNode);
|
||||
|
||||
SearchResults runFuzzySearch(const std::string& query) const;
|
||||
std::vector<SearchMatch> runFuzzySearchAndGetMatches(const std::string& query) const;
|
||||
|
||||
@@ -19,6 +19,18 @@ SearchNode::~SearchNode()
|
||||
{
|
||||
}
|
||||
|
||||
size_t SearchNode::getNodeCount() const
|
||||
{
|
||||
size_t count = 1;
|
||||
|
||||
for (std::shared_ptr<SearchNode> n: m_nodes)
|
||||
{
|
||||
count += n->getNodeCount();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
const std::string& SearchNode::getName() const
|
||||
{
|
||||
return m_name;
|
||||
@@ -28,7 +40,7 @@ std::vector<std::string> SearchNode::getNameHierarchy() const
|
||||
{
|
||||
std::vector<std::string> nameHierarchy;
|
||||
const SearchNode* parent = getParent();
|
||||
if (parent)
|
||||
if (parent && parent->m_nameId)
|
||||
{
|
||||
nameHierarchy = parent->getNameHierarchy();
|
||||
}
|
||||
@@ -53,6 +65,22 @@ Id SearchNode::getNameId() const
|
||||
return m_nameId;
|
||||
}
|
||||
|
||||
std::deque<Id> SearchNode::getNameIdsRecursive() const
|
||||
{
|
||||
std::deque<Id> ids;
|
||||
|
||||
ids.push_front(m_nameId);
|
||||
|
||||
SearchNode* parent = m_parent;
|
||||
while (parent && parent->m_nameId)
|
||||
{
|
||||
ids.push_front(parent->getNameId());
|
||||
parent = parent->getParent();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
Id SearchNode::getFirstTokenId() const
|
||||
{
|
||||
if (m_tokenIds.size())
|
||||
@@ -68,14 +96,37 @@ const std::set<Id>& SearchNode::getTokenIds() const
|
||||
return m_tokenIds;
|
||||
}
|
||||
|
||||
bool SearchNode::hasTokenIdsRecursive() const
|
||||
{
|
||||
if (m_tokenIds.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (std::shared_ptr<SearchNode> n: m_nodes)
|
||||
{
|
||||
if (n->hasTokenIdsRecursive())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SearchNode::addTokenId(Id tokenId)
|
||||
{
|
||||
m_tokenIds.insert(tokenId);
|
||||
}
|
||||
|
||||
void SearchNode::removeTokenId(Id tokenId)
|
||||
{
|
||||
m_tokenIds.erase(tokenId);
|
||||
}
|
||||
|
||||
SearchNode* SearchNode::getParent() const
|
||||
{
|
||||
if (m_parent && m_parent->m_nameId)
|
||||
if (m_parent)
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
@@ -183,6 +234,18 @@ std::shared_ptr<SearchNode> SearchNode::getNodeRecursive(std::deque<Id>* nameIds
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SearchNode::removeSearchNode(SearchNode* node)
|
||||
{
|
||||
for (std::set<std::shared_ptr<SearchNode>>::iterator it = m_nodes.begin(); it != m_nodes.end(); it++)
|
||||
{
|
||||
if ((*it)->m_nameId == node->m_nameId)
|
||||
{
|
||||
m_nodes.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SearchMatch SearchNode::fuzzyMatchData(const std::string& query, const SearchNode* parent) const
|
||||
{
|
||||
SearchMatch data;
|
||||
|
||||
@@ -22,15 +22,21 @@ public:
|
||||
SearchNode(SearchNode* parent, const std::string& name, Id nameId);
|
||||
~SearchNode();
|
||||
|
||||
size_t getNodeCount() const;
|
||||
|
||||
const std::string& getName() const;
|
||||
std::vector<std::string> getNameHierarchy() const;
|
||||
std::string getFullName() const;
|
||||
|
||||
Id getNameId() const;
|
||||
std::deque<Id> getNameIdsRecursive() const;
|
||||
|
||||
Id getFirstTokenId() const;
|
||||
const std::set<Id>& getTokenIds() const;
|
||||
bool hasTokenIdsRecursive() const;
|
||||
|
||||
void addTokenId(Id tokenId);
|
||||
void removeTokenId(Id tokenId);
|
||||
|
||||
SearchNode* getParent() const;
|
||||
std::deque<SearchNode*> getParentsWithoutTokenId();
|
||||
@@ -46,11 +52,12 @@ private:
|
||||
typedef std::multimap<size_t, const SearchNode*> FuzzyMap;
|
||||
typedef FuzzyMap::const_iterator FuzzyMapIterator;
|
||||
|
||||
|
||||
// Accessed by SearchIndex
|
||||
std::shared_ptr<SearchNode> addNodeRecursive(std::deque<Id>* nameIds, const Dictionary& dictionary);
|
||||
std::shared_ptr<SearchNode> getNodeRecursive(std::deque<Id>* nameIds) const;
|
||||
|
||||
void removeSearchNode(SearchNode* node);
|
||||
|
||||
SearchMatch fuzzyMatchData(const std::string& query, const SearchNode* parent) const;
|
||||
|
||||
friend class SearchIndex;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "utility/FileSystem.h"
|
||||
|
||||
#include "boost/date_time.hpp"
|
||||
#include "boost/filesystem.hpp"
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
std::vector<std::string> FileSystem::getSourceFilesFromDirectory(
|
||||
std::vector<std::string> FileSystem::getFileNamesFromDirectory(
|
||||
const std::string& path, const std::vector<std::string>& extensions
|
||||
){
|
||||
)
|
||||
{
|
||||
std::vector<std::string> files;
|
||||
|
||||
if (boost::filesystem::is_directory(path))
|
||||
@@ -25,25 +25,37 @@ std::vector<std::string> FileSystem::getSourceFilesFromDirectory(
|
||||
return files;
|
||||
}
|
||||
|
||||
std::vector<std::string> FileSystem::getFileNamesFromDirectory(
|
||||
const std::string& path, const std::vector<std::string>& extensions
|
||||
)
|
||||
{
|
||||
return getSourceFilesFromDirectory(path, extensions);
|
||||
}
|
||||
std::vector<std::string> FileSystem::getFileNamesFromDirectoryUpdatedAfter(
|
||||
const std::string& path, const std::vector<std::string>& extensions, const std::string& timeString
|
||||
){
|
||||
std::vector<std::string> files;
|
||||
|
||||
bool FileSystem::isValidExtension(const std::string& filepath, const std::vector<std::string>& extensions)
|
||||
{
|
||||
boost::filesystem::path path(filepath);
|
||||
const boost::posix_time::ptime time = boost::posix_time::from_iso_string(timeString);
|
||||
|
||||
for (std::string extension : extensions)
|
||||
if (boost::filesystem::is_directory(path))
|
||||
{
|
||||
if (path.extension() == extension)
|
||||
boost::filesystem::recursive_directory_iterator it(path);
|
||||
boost::filesystem::recursive_directory_iterator endit;
|
||||
while (it != endit)
|
||||
{
|
||||
return true;
|
||||
if (boost::filesystem::is_regular_file(*it) && isValidExtension(it->path().string(), extensions))
|
||||
{
|
||||
std::time_t t = boost::filesystem::last_write_time(*it);
|
||||
boost::posix_time::ptime lastWriteTime = boost::posix_time::from_time_t(t);
|
||||
if (lastWriteTime >= time)
|
||||
{
|
||||
files.push_back(it->path().generic_string());
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return files;
|
||||
}
|
||||
|
||||
std::string FileSystem::getTimeStringNow()
|
||||
{
|
||||
return boost::posix_time::to_iso_string(boost::posix_time::second_clock::universal_time());
|
||||
}
|
||||
|
||||
bool FileSystem::exists(const std::string& path)
|
||||
@@ -64,4 +76,33 @@ std::string FileSystem::extension(const std::string& path)
|
||||
std::string FileSystem::filePathWithoutExtension(const std::string& path)
|
||||
{
|
||||
return boost::filesystem::path(path).replace_extension().generic_string();
|
||||
}
|
||||
}
|
||||
|
||||
std::string FileSystem::absoluteFilePath(const std::string& path)
|
||||
{
|
||||
return boost::filesystem::absolute(boost::filesystem::path(path)).generic_string();
|
||||
}
|
||||
|
||||
bool FileSystem::equivalent(const std::string& pathA, const std::string& pathB)
|
||||
{
|
||||
if (exists(pathA) && exists(pathB))
|
||||
{
|
||||
return boost::filesystem::equivalent(boost::filesystem::path(pathA), boost::filesystem::path(pathB));
|
||||
}
|
||||
|
||||
return boost::filesystem::path(pathA).compare(boost::filesystem::path(pathB)) == 0;
|
||||
}
|
||||
|
||||
bool FileSystem::isValidExtension(const std::string& filepath, const std::vector<std::string>& extensions)
|
||||
{
|
||||
boost::filesystem::path path(filepath);
|
||||
|
||||
for (std::string extension : extensions)
|
||||
{
|
||||
if (path.extension() == extension)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,18 +7,20 @@
|
||||
class FileSystem
|
||||
{
|
||||
public:
|
||||
static std::vector<std::string> getSourceFilesFromDirectory( // TODO: Replace this with getFileNamesFromDirectory.
|
||||
const std::string& path, const std::vector<std::string>& extensions
|
||||
);
|
||||
|
||||
static std::vector<std::string> getFileNamesFromDirectory(
|
||||
const std::string& path, const std::vector<std::string>& extensions
|
||||
);
|
||||
const std::string& path, const std::vector<std::string>& extensions);
|
||||
static std::vector<std::string> getFileNamesFromDirectoryUpdatedAfter(
|
||||
const std::string& path, const std::vector<std::string>& extensions, const std::string& timeString);
|
||||
|
||||
static std::string getTimeStringNow();
|
||||
|
||||
static bool exists(const std::string& path);
|
||||
static std::string fileName(const std::string& path);
|
||||
static std::string extension(const std::string& path);
|
||||
static std::string filePathWithoutExtension(const std::string& path);
|
||||
static std::string absoluteFilePath(const std::string& path);
|
||||
|
||||
static bool equivalent(const std::string& pathA, const std::string& pathB);
|
||||
|
||||
private:
|
||||
static bool isValidExtension(const std::string& filepath, const std::vector<std::string>& extensions);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef MESSAGE_AUTO_REFRESH_CHANGED_H
|
||||
#define MESSAGE_AUTO_REFRESH_CHANGED_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
|
||||
class MessageAutoRefreshChanged: public Message<MessageAutoRefreshChanged>
|
||||
{
|
||||
public:
|
||||
MessageAutoRefreshChanged(bool enabled)
|
||||
: enabled(enabled)
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageAutoRefreshChanged";
|
||||
}
|
||||
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_AUTO_REFRESH_CHANGED_H
|
||||
@@ -6,8 +6,9 @@
|
||||
class MessageFinishedParsing: public Message<MessageFinishedParsing>
|
||||
{
|
||||
public:
|
||||
MessageFinishedParsing(float parseTime, size_t errorCount)
|
||||
: parseTime(parseTime)
|
||||
MessageFinishedParsing(size_t fileCount, float parseTime, size_t errorCount)
|
||||
: fileCount(fileCount)
|
||||
, parseTime(parseTime)
|
||||
, errorCount(errorCount)
|
||||
{
|
||||
}
|
||||
@@ -17,6 +18,7 @@ public:
|
||||
return "MessageFinishedParsing";
|
||||
}
|
||||
|
||||
size_t fileCount;
|
||||
float parseTime;
|
||||
size_t errorCount;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define MESSAGE_REFRESH_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
class MessageRefresh: public Message<MessageRefresh>
|
||||
{
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef MESSAGE_WINDOW_FOCUS_H
|
||||
#define MESSAGE_WINDOW_FOCUS_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
|
||||
class MessageWindowFocus: public Message<MessageWindowFocus>
|
||||
{
|
||||
public:
|
||||
MessageWindowFocus()
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageWindowFocus";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MESSAGE_WINDOW_FOCUS_H
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "cxxtest/TestSuite.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -15,7 +16,7 @@ public:
|
||||
extensions.push_back(".cpp");
|
||||
|
||||
std::vector<std::string> cppFiles =
|
||||
FileSystem::getSourceFilesFromDirectory("data/FileSystemTestSuite", extensions);
|
||||
FileSystem::getFileNamesFromDirectory("data/FileSystemTestSuite", extensions);
|
||||
|
||||
TS_ASSERT_EQUALS(cppFiles.size(), 2);
|
||||
TS_ASSERT(isInVector(cppFiles, "data/FileSystemTestSuite/main.cpp"));
|
||||
@@ -28,7 +29,7 @@ public:
|
||||
extensions.push_back(".h");
|
||||
|
||||
std::vector<std::string> headerFiles =
|
||||
FileSystem::getSourceFilesFromDirectory("data/FileSystemTestSuite", extensions);
|
||||
FileSystem::getFileNamesFromDirectory("data/FileSystemTestSuite", extensions);
|
||||
|
||||
TS_ASSERT_EQUALS(headerFiles.size(), 2);
|
||||
TS_ASSERT(isInVector(headerFiles, "data/FileSystemTestSuite/tictactoe.h"));
|
||||
@@ -43,11 +44,33 @@ public:
|
||||
extensions.push_back(".cpp");
|
||||
|
||||
std::vector<std::string> sourceFiles =
|
||||
FileSystem::getSourceFilesFromDirectory("data/FileSystemTestSuite", extensions);
|
||||
FileSystem::getFileNamesFromDirectory("data/FileSystemTestSuite", extensions);
|
||||
|
||||
TS_ASSERT_EQUALS(sourceFiles.size(), 5);
|
||||
}
|
||||
|
||||
void test_find_updated_source_files()
|
||||
{
|
||||
std::string timeString = FileSystem::getTimeStringNow();
|
||||
|
||||
std::fstream fileStream;
|
||||
fileStream.open("./data/FileSystemTestSuite/update.c");
|
||||
fileStream << "update";
|
||||
fileStream.close();
|
||||
|
||||
std::vector<std::string> extensions;
|
||||
extensions.push_back(".h");
|
||||
extensions.push_back(".c");
|
||||
extensions.push_back(".hpp");
|
||||
extensions.push_back(".cpp");
|
||||
|
||||
std::vector<std::string> sourceFiles =
|
||||
FileSystem::getFileNamesFromDirectoryUpdatedAfter("data/FileSystemTestSuite", extensions, timeString);
|
||||
|
||||
TS_ASSERT_EQUALS(sourceFiles.size(), 1);
|
||||
TS_ASSERT_EQUALS(sourceFiles[0], "data/FileSystemTestSuite/update.c");
|
||||
}
|
||||
|
||||
void test_filesystem_finds_existing_files()
|
||||
{
|
||||
TS_ASSERT(FileSystem::exists("data/FileSystemTestSuite"));
|
||||
|
||||
@@ -245,6 +245,21 @@ public:
|
||||
TS_ASSERT_EQUALS(children[1], &c);
|
||||
}
|
||||
|
||||
void test_node_has_references()
|
||||
{
|
||||
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||
Node c(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("C", "::")));
|
||||
Node d(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("D", "::")));
|
||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||
Edge e3(Edge::EDGE_USAGE, &c, &d);
|
||||
|
||||
TS_ASSERT(a.hasReferences());
|
||||
TS_ASSERT(!b.hasReferences());
|
||||
TS_ASSERT(c.hasReferences());
|
||||
}
|
||||
|
||||
void test_graph_saves_nodes()
|
||||
{
|
||||
Graph graph;
|
||||
@@ -294,6 +309,58 @@ public:
|
||||
TS_ASSERT_EQUALS(Edge::EDGE_CALL, graph.getEdgeById(e.getId())->getType());
|
||||
}
|
||||
|
||||
void test_graph_removes_nodes()
|
||||
{
|
||||
Graph graph;
|
||||
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||
|
||||
graph.addNode(&a);
|
||||
graph.addNode(&b);
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
graph.removeNode(graph.getNodeById(a.getId()));
|
||||
|
||||
TS_ASSERT_EQUALS(1, graph.getNodeCount());
|
||||
}
|
||||
|
||||
void test_graph_removes_unreferenced_nodes()
|
||||
{
|
||||
Graph graph;
|
||||
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||
Node c(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("C", "::")));
|
||||
Node d(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("D", "::")));
|
||||
Node e(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("E", "::")));
|
||||
|
||||
Edge e1(Edge::EDGE_MEMBER, &a, &b);
|
||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||
Edge e3(Edge::EDGE_USAGE, &c, &d);
|
||||
Edge e4(Edge::EDGE_MEMBER, &b, &e);
|
||||
|
||||
graph.addNode(&a);
|
||||
graph.addNode(&b);
|
||||
graph.addNode(&c);
|
||||
graph.addNode(&d);
|
||||
graph.addNode(&e);
|
||||
|
||||
graph.addEdge(&e1);
|
||||
graph.addEdge(&e2);
|
||||
graph.addEdge(&e3);
|
||||
graph.addEdge(&e4);
|
||||
|
||||
TS_ASSERT_EQUALS(5, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(4, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(!graph.removeNodeIfUnreferencedRecursive(graph.getNodeById(a.getId())));
|
||||
TS_ASSERT(graph.removeNodeIfUnreferencedRecursive(graph.getNodeById(b.getId())));
|
||||
|
||||
TS_ASSERT_EQUALS(3, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(2, graph.getEdgeCount());
|
||||
}
|
||||
|
||||
private:
|
||||
class TestToken: public Token
|
||||
{
|
||||
|
||||
@@ -17,7 +17,8 @@ public:
|
||||
|
||||
TS_ASSERT(node->getNameId());
|
||||
TS_ASSERT(!node->getFirstTokenId());
|
||||
TS_ASSERT(!node->getParent());
|
||||
TS_ASSERT(node->getParent());
|
||||
TS_ASSERT(!node->getParent()->getNameId());
|
||||
}
|
||||
|
||||
void test_get_node()
|
||||
@@ -32,7 +33,8 @@ public:
|
||||
|
||||
TS_ASSERT(node->getNameId());
|
||||
TS_ASSERT(!node->getFirstTokenId());
|
||||
TS_ASSERT(!node->getParent());
|
||||
TS_ASSERT(node->getParent());
|
||||
TS_ASSERT(!node->getParent()->getNameId());
|
||||
|
||||
node = index.getNode("math");
|
||||
TS_ASSERT(!node);
|
||||
@@ -72,6 +74,55 @@ public:
|
||||
TS_ASSERT_EQUALS(node1->getParent(), node2->getParent());
|
||||
}
|
||||
|
||||
void test_remove_nodes()
|
||||
{
|
||||
SearchIndex index;
|
||||
index.addNode(utility::splitToVector("util::math::pow", "::"));
|
||||
index.addNode(utility::splitToVector("util::math::floor", "::"));
|
||||
|
||||
index.removeNode(index.getNode("util::math::pow"));
|
||||
|
||||
TS_ASSERT(!index.getNode("util::math::pow"));
|
||||
TS_ASSERT(index.getNode("util::math::floor"));
|
||||
TS_ASSERT(index.getNode("util::math"));
|
||||
|
||||
index.removeNode(index.getNode("util::math"));
|
||||
|
||||
TS_ASSERT(!index.getNode("util::math::floor"));
|
||||
TS_ASSERT(!index.getNode("util::math"));
|
||||
TS_ASSERT(index.getNode("util"));
|
||||
}
|
||||
|
||||
void test_remove_unreferenced_nodes()
|
||||
{
|
||||
SearchIndex index;
|
||||
SearchNode* node1 = index.addNode(utility::splitToVector("util::math::pow", "::"));
|
||||
SearchNode* node2 = index.addNode(utility::splitToVector("util::math::floor", "::"));
|
||||
|
||||
node1->addTokenId(1);
|
||||
node2->addTokenId(2);
|
||||
|
||||
TS_ASSERT(index.getNode("util")->hasTokenIdsRecursive());
|
||||
|
||||
TS_ASSERT(!index.removeNodeIfUnreferencedRecursive(index.getNode("util")));
|
||||
TS_ASSERT(!index.removeNodeIfUnreferencedRecursive(index.getNode("util::math")));
|
||||
TS_ASSERT(!index.removeNodeIfUnreferencedRecursive(index.getNode("util::math::pow")));
|
||||
|
||||
node1->removeTokenId(1);
|
||||
|
||||
TS_ASSERT(index.removeNodeIfUnreferencedRecursive(index.getNode("util::math::pow")));
|
||||
TS_ASSERT(!index.getNode("util::math::pow"));
|
||||
TS_ASSERT(index.getNode("util::math"));
|
||||
TS_ASSERT(index.getNode("util"));
|
||||
|
||||
node2->removeTokenId(2);
|
||||
|
||||
TS_ASSERT(index.removeNodeIfUnreferencedRecursive(index.getNode("util::math")));
|
||||
|
||||
TS_ASSERT(!index.getNode("util::math"));
|
||||
TS_ASSERT(!index.getNode("util"));
|
||||
}
|
||||
|
||||
void test_clear()
|
||||
{
|
||||
SearchIndex index;
|
||||
@@ -83,6 +134,7 @@ public:
|
||||
index.clear();
|
||||
|
||||
TS_ASSERT(!index.getNode("math"));
|
||||
TS_ASSERT(!index.getNode("string"));
|
||||
}
|
||||
|
||||
void test_fuzzy_matching()
|
||||
|
||||
+135
-2
@@ -15,6 +15,11 @@
|
||||
class StorageTestSuite: public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
m_filePath = "file.cpp";
|
||||
}
|
||||
|
||||
void test_storage_saves_typedef()
|
||||
{
|
||||
TestStorage storage;
|
||||
@@ -536,6 +541,117 @@ public:
|
||||
TS_ASSERT(isValidLocation(locations[0], 0));
|
||||
}
|
||||
|
||||
void test_storage_clears_single_file_data_of_single_file_storage()
|
||||
{
|
||||
TestStorage storage;
|
||||
storage.onFunctionParsed(
|
||||
validLocation(), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"),
|
||||
parameters("char")), validLocation()
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 3);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 2);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 4);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 3);
|
||||
|
||||
storage.clearFileData(std::vector<std::string>(1, m_filePath));
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 0);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 0);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 0);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 0);
|
||||
}
|
||||
|
||||
void test_storage_clears_unreferenced_single_file_data_of_multi_file_storage()
|
||||
{
|
||||
m_filePath = "file.h";
|
||||
|
||||
TestStorage storage;
|
||||
|
||||
ParseFunction isTrue = ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char"));
|
||||
storage.onFunctionParsed(validLocation(), isTrue, validLocation());
|
||||
|
||||
m_filePath = "file.cpp";
|
||||
|
||||
ParseFunction main = ParseFunction(typeUsage("int"), utility::splitToVector("main", "::"), parameters("void"));
|
||||
storage.onFunctionParsed(validLocation(), main, validLocation());
|
||||
|
||||
storage.onCallParsed(validLocation(), main, isTrue);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 6);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 5);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 6);
|
||||
|
||||
storage.clearFileData(std::vector<std::string>(1, "file.cpp"));
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 3);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 2);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 4);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 3);
|
||||
}
|
||||
|
||||
void test_storage_clears_referenced_single_file_data_of_multi_file_storage()
|
||||
{
|
||||
m_filePath = "file.h";
|
||||
|
||||
TestStorage storage;
|
||||
|
||||
ParseFunction isTrue = ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("void"));
|
||||
storage.onFunctionParsed(validLocation(), isTrue, validLocation());
|
||||
|
||||
m_filePath = "file.cpp";
|
||||
|
||||
ParseFunction main = ParseFunction(typeUsage("int"), utility::splitToVector("main", "::"), parameters("void"));
|
||||
storage.onFunctionParsed(validLocation(), main, validLocation());
|
||||
|
||||
storage.onCallParsed(validLocation(), main, isTrue);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 5);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 5);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 5);
|
||||
|
||||
storage.clearFileData(std::vector<std::string>(1, "file.h"));
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 4);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 3);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 5);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 4);
|
||||
}
|
||||
|
||||
void test_storage_clears_multi_file_data_of_multi_file_storage()
|
||||
{
|
||||
m_filePath = "file.h";
|
||||
|
||||
TestStorage storage;
|
||||
|
||||
ParseFunction isTrue = ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("void"));
|
||||
storage.onFunctionParsed(validLocation(), isTrue, validLocation());
|
||||
|
||||
m_filePath = "file.cpp";
|
||||
|
||||
ParseFunction main = ParseFunction(typeUsage("int"), utility::splitToVector("main", "::"), parameters("void"));
|
||||
storage.onFunctionParsed(validLocation(), main, validLocation());
|
||||
|
||||
storage.onCallParsed(validLocation(), main, isTrue);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 5);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 5);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 5);
|
||||
|
||||
std::vector<std::string> filePaths;
|
||||
filePaths.push_back("file.cpp");
|
||||
filePaths.push_back("file.h");
|
||||
storage.clearFileData(filePaths);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 0);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 0);
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 0);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 0);
|
||||
}
|
||||
|
||||
private:
|
||||
class TestStorage
|
||||
: public Storage
|
||||
@@ -568,17 +684,32 @@ private:
|
||||
{
|
||||
return getSearchIndex().getWord(wordId);
|
||||
}
|
||||
|
||||
const Graph& graph() const
|
||||
{
|
||||
return getGraph();
|
||||
}
|
||||
|
||||
const TokenLocationCollection& tokenLocationCollection() const
|
||||
{
|
||||
return getTokenLocationCollection();
|
||||
}
|
||||
|
||||
const SearchIndex& searchIndex() const
|
||||
{
|
||||
return getSearchIndex();
|
||||
}
|
||||
};
|
||||
|
||||
ParseLocation validLocation(Id locationId = 0) const
|
||||
{
|
||||
return ParseLocation("file.cpp", 1, locationId, 1, locationId);
|
||||
return ParseLocation(m_filePath, 1, locationId, 1, locationId);
|
||||
}
|
||||
|
||||
bool isValidLocation(TokenLocation* location, Id locationId) const
|
||||
{
|
||||
return
|
||||
location->getFilePath() == "file.cpp" &&
|
||||
location->getFilePath() == m_filePath &&
|
||||
location->getLineNumber() == 1 &&
|
||||
location->getColumnNumber() == locationId;
|
||||
}
|
||||
@@ -594,4 +725,6 @@ private:
|
||||
params.push_back(typeUsage(param));
|
||||
return params;
|
||||
}
|
||||
|
||||
std::string m_filePath;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user