From 8242454104e50596d05eb47630e8634c46dc4b8c Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Thu, 8 Jan 2015 12:12:50 +0100 Subject: [PATCH] ui/data: cleaned up UI and parsing * HOT FIX: typename not always correctly split to name hierarchy * show node main if available as first active token after parsing * show all contents of namespaces if searched for * added missing enum type and enum value usages * added inheritance for structs * removed MessageActivateToken and replaced it with MessageActivateTokens * activating correct nodes for clicks in GraphView and CodeView * no graph change when clicking an edge, but highlighting the edge instead * only show active nodes without connections when multiple are activated * fixed snippet sorting to put file that contains declarations on top * set sizeHints on CodeView and SearchView to increase their initial size fortune cookie message = Das Leben wird eine positive Wendung nehmen. --- bin/test/data/log/test_log.txt | 3 + src/app/qt/element/QtCodeFileList.cpp | 5 + src/app/qt/element/QtCodeFileList.h | 2 + src/app/qt/element/QtCodeSnippet.cpp | 15 +- src/app/qt/element/QtCodeSnippet.h | 1 + src/app/qt/element/QtSearchBar.cpp | 5 + src/app/qt/element/QtSearchBar.h | 2 + src/app/qt/view/QtCodeView.cpp | 69 ++++---- src/app/qt/view/QtCodeView.h | 12 +- src/app/qt/view/graphElements/QtGraphEdge.cpp | 9 +- src/app/qt/view/graphElements/QtGraphNode.cpp | 4 +- src/lib/Application.cpp | 20 ++- src/lib/Application.h | 2 + src/lib/CMakeLists.txt | 2 +- .../component/controller/CodeController.cpp | 157 +++++++++--------- src/lib/component/controller/CodeController.h | 22 +-- .../component/controller/GraphController.cpp | 42 +++-- .../component/controller/GraphController.h | 6 +- .../component/controller/SearchController.cpp | 23 +-- .../component/controller/SearchController.h | 5 +- src/lib/component/view/CodeView.cpp | 27 +-- src/lib/component/view/CodeView.h | 14 +- src/lib/data/Storage.cpp | 152 +++++++++++++---- src/lib/data/Storage.h | 13 +- src/lib/data/access/GraphAccess.h | 3 +- src/lib/data/access/GraphAccessProxy.cpp | 12 +- src/lib/data/access/GraphAccessProxy.h | 3 +- src/lib/data/parser/ParserClient.h | 5 + src/lib/data/parser/cxx/ASTBodyVisitor.cpp | 27 ++- src/lib/data/parser/cxx/ASTBodyVisitor.h | 1 + .../data/parser/cxx/ASTBodyVisitorClient.h | 6 +- src/lib/data/parser/cxx/ASTVisitor.cpp | 74 +++++++-- src/lib/data/parser/cxx/ASTVisitor.h | 17 +- src/lib/data/type/DataType.cpp | 2 +- src/lib/data/type/DataType.h | 2 +- .../messaging/type/MessageActivateToken.h | 23 --- .../type/MessageActivateTokenLocation.h | 23 +++ .../messaging/type/MessageActivateTokens.h | 12 ++ .../utility/messaging/type/MessageShowFile.h | 6 +- src/test/CxxParserTestSuite.h | 142 +++++++++++++++- src/test/StorageTestSuite.h | 27 ++- 41 files changed, 703 insertions(+), 294 deletions(-) delete mode 100644 src/lib/utility/messaging/type/MessageActivateToken.h create mode 100644 src/lib/utility/messaging/type/MessageActivateTokenLocation.h diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 3e822d83..51cd5b6e 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -88,6 +88,9 @@ Storage.cpp INFO: enum field: VALUE Storage.cpp INFO: class: ClassA Storage.cpp INFO: class: ClassB Storage.cpp INFO: inheritance: ClassB : ClassA +Storage.cpp INFO: struct: StructA +Storage.cpp INFO: struct: StructB +Storage.cpp INFO: inheritance: StructB : StructA Storage.cpp INFO: function: isTrue Storage.cpp INFO: function: func Storage.cpp INFO: call: isTrue -> func diff --git a/src/app/qt/element/QtCodeFileList.cpp b/src/app/qt/element/QtCodeFileList.cpp index b32a2a68..ed83f4df 100644 --- a/src/app/qt/element/QtCodeFileList.cpp +++ b/src/app/qt/element/QtCodeFileList.cpp @@ -28,6 +28,11 @@ QtCodeFileList::~QtCodeFileList() { } +QSize QtCodeFileList::sizeHint() const +{ + return QSize(800, 800); +} + void QtCodeFileList::addCodeSnippet( uint startLineNumber, const std::string& code, diff --git a/src/app/qt/element/QtCodeFileList.h b/src/app/qt/element/QtCodeFileList.h index 2a3fa433..278bd5e7 100644 --- a/src/app/qt/element/QtCodeFileList.h +++ b/src/app/qt/element/QtCodeFileList.h @@ -20,6 +20,8 @@ public: QtCodeFileList(QWidget* parent = 0); virtual ~QtCodeFileList(); + virtual QSize sizeHint() const; + void addCodeSnippet( uint startLineNumber, const std::string& code, diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp index 60aae718..43f6a05e 100644 --- a/src/app/qt/element/QtCodeSnippet.cpp +++ b/src/app/qt/element/QtCodeSnippet.cpp @@ -9,7 +9,7 @@ #include "data/location/TokenLocation.h" #include "data/location/TokenLocationFile.h" #include "qt/utility/QtHighlighter.h" -#include "utility/messaging/type/MessageActivateToken.h" +#include "utility/messaging/type/MessageActivateTokenLocation.h" #include "utility/messaging/type/MessageShowFile.h" QtCodeSnippet::LineNumberArea::LineNumberArea(QtCodeSnippet *codeSnippet) @@ -226,7 +226,7 @@ void QtCodeSnippet::clickedTokenLocation() { int clickPosition = textCursor().position(); int diff = endTextEditPosition() + 1; - Id tokenId = 0; + Id locationId = 0; for (Annotation annotation : m_annotations) { @@ -236,22 +236,20 @@ void QtCodeSnippet::clickedTokenLocation() if (d < diff) { diff = d; - tokenId = annotation.tokenId; + locationId = annotation.locationId; } } } - if (tokenId) + if (locationId) { - MessageActivateToken(tokenId).dispatch(); + MessageActivateTokenLocation(locationId).dispatch(); } } void QtCodeSnippet::clickedMaximizeButton() { - MessageShowFile( - m_filePath, m_startLineNumber, m_startLineNumber + document()->blockCount() - 1, m_activeTokenIds - ).dispatch(); + MessageShowFile(m_filePath, m_startLineNumber, m_startLineNumber + document()->blockCount() - 1).dispatch(); } void QtCodeSnippet::clearSelection() @@ -292,6 +290,7 @@ void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile) } annotation.tokenId = location->getTokenId(); + annotation.locationId = location->getId(); annotation.isScope = location->getType() == TokenLocation::LOCATION_SCOPE; m_annotations.push_back(annotation); diff --git a/src/app/qt/element/QtCodeSnippet.h b/src/app/qt/element/QtCodeSnippet.h index c4b902e0..d70f6ff3 100644 --- a/src/app/qt/element/QtCodeSnippet.h +++ b/src/app/qt/element/QtCodeSnippet.h @@ -75,6 +75,7 @@ private: int start; int end; Id tokenId; + Id locationId; bool isScope; }; diff --git a/src/app/qt/element/QtSearchBar.cpp b/src/app/qt/element/QtSearchBar.cpp index 03f2e4e9..dc702ad6 100644 --- a/src/app/qt/element/QtSearchBar.cpp +++ b/src/app/qt/element/QtSearchBar.cpp @@ -52,6 +52,11 @@ QtSearchBar::~QtSearchBar() { } +QSize QtSearchBar::sizeHint() const +{ + return QSize(400, 100); +} + void QtSearchBar::setText(const std::string& text) { m_searchBox->setQuery(text); diff --git a/src/app/qt/element/QtSearchBar.h b/src/app/qt/element/QtSearchBar.h index e1499d76..fdb3bfd9 100644 --- a/src/app/qt/element/QtSearchBar.h +++ b/src/app/qt/element/QtSearchBar.h @@ -20,6 +20,8 @@ public: QtSearchBar(); virtual ~QtSearchBar(); + virtual QSize sizeHint() const; + void setText(const std::string& text); void setFocus(); void setAutocompletionList(const std::vector& autocompletionList); diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp index 3ac91bdd..fb647c3c 100644 --- a/src/app/qt/view/QtCodeView.cpp +++ b/src/app/qt/view/QtCodeView.cpp @@ -11,8 +11,8 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout) : CodeView(viewLayout) , m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this)) , m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this)) + , m_showCodeSnippetsFunctor(std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1)) , m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1)) - , m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1)) { m_widget = createQtCodeFileList(); } @@ -35,21 +35,26 @@ void QtCodeView::refreshView() m_refreshViewFunctor(); } -void QtCodeView::showCodeFile(const CodeSnippetParams& params) -{ - m_showCodeFileFunctor(params); -} - -void QtCodeView::addCodeSnippet(const CodeSnippetParams& params) -{ - m_addCodeSnippetFunctor(params); -} - void QtCodeView::clearCodeSnippets() { m_clearCodeSnippetsFunctor(); } +void QtCodeView::setActiveTokenIds(const std::vector& activeTokenIds) +{ + m_activeTokenIds = activeTokenIds; +} + +void QtCodeView::showCodeSnippets(const std::vector& snippets) +{ + m_showCodeSnippetsFunctor(snippets); +} + +void QtCodeView::showCodeFile(const CodeSnippetParams& params) +{ + m_showCodeFileFunctor(params); +} + void QtCodeView::doRefreshView() { setStyleSheet(m_widget.get()); @@ -61,6 +66,27 @@ void QtCodeView::doRefreshView() } } +void QtCodeView::doClearCodeSnippets() +{ + m_widget->clearCodeSnippets(); +} + +void QtCodeView::doShowCodeSnippets(const std::vector& snippets) +{ + doClearCodeSnippets(); + + clearClosedWindows(); + for (std::shared_ptr window: m_windows) + { + window->setActiveTokenIds(m_activeTokenIds); + } + + for (const CodeSnippetParams& params : snippets) + { + m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, m_activeTokenIds); + } +} + void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) { std::shared_ptr ptr = createQtCodeFileList(); @@ -79,22 +105,6 @@ void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) ptr->verticalScrollBar()->setValue(min + (max - min) * percent); } -void QtCodeView::doAddCodeSnippet(const CodeSnippetParams& params) -{ - m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, m_activeTokenIds); - - clearClosedWindows(); - for (std::shared_ptr window: m_windows) - { - window->setActiveTokenIds(m_activeTokenIds); - } -} - -void QtCodeView::doClearCodeSnippets() -{ - m_widget->clearCodeSnippets(); -} - std::shared_ptr QtCodeView::createQtCodeFileList() const { std::shared_ptr ptr = std::make_shared(); @@ -107,11 +117,6 @@ void QtCodeView::setStyleSheet(QWidget* widget) const widget->setStyleSheet(TextAccess::createFromFile("data/gui/code_view/code_view.css")->getText().c_str()); } -void QtCodeView::setActiveTokenIds(std::vector ids) -{ - m_activeTokenIds = ids; -} - void QtCodeView::clearClosedWindows() { for (size_t i = 0; i < m_windows.size(); i++) diff --git a/src/app/qt/view/QtCodeView.h b/src/app/qt/view/QtCodeView.h index 98954977..61593717 100644 --- a/src/app/qt/view/QtCodeView.h +++ b/src/app/qt/view/QtCodeView.h @@ -24,26 +24,26 @@ public: virtual void refreshView(); // CodeView implementation - virtual void showCodeFile(const CodeSnippetParams& params); - virtual void addCodeSnippet(const CodeSnippetParams& params); virtual void clearCodeSnippets(); + virtual void setActiveTokenIds(const std::vector& activeTokenIds); + virtual void showCodeSnippets(const std::vector& snippets); + virtual void showCodeFile(const CodeSnippetParams& params); private: void doRefreshView(); - void doShowCodeFile(const CodeSnippetParams& params); - void doAddCodeSnippet(const CodeSnippetParams& params); void doClearCodeSnippets(); + void doShowCodeSnippets(const std::vector& snippets); + void doShowCodeFile(const CodeSnippetParams& params); std::shared_ptr createQtCodeFileList() const; void setStyleSheet(QWidget* widget) const; - void setActiveTokenIds(std::vector ids); void clearClosedWindows(); QtThreadedFunctor<> m_refreshViewFunctor; QtThreadedFunctor<> m_clearCodeSnippetsFunctor; + QtThreadedFunctor&> m_showCodeSnippetsFunctor; QtThreadedFunctor m_showCodeFileFunctor; - QtThreadedFunctor m_addCodeSnippetFunctor; std::shared_ptr m_widget; std::vector> m_windows; diff --git a/src/app/qt/view/graphElements/QtGraphEdge.cpp b/src/app/qt/view/graphElements/QtGraphEdge.cpp index 41a3ae85..c85bcd64 100644 --- a/src/app/qt/view/graphElements/QtGraphEdge.cpp +++ b/src/app/qt/view/graphElements/QtGraphEdge.cpp @@ -7,7 +7,6 @@ #include #include -#include "utility/messaging/type/MessageActivateToken.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "component/view/graphElements/GraphNode.h" @@ -460,11 +459,15 @@ void QtGraphEdge::onClick() if (isAggregation()) { const std::set& ids = getData()->getComponent()->getAggregationIds(); - MessageActivateTokens(std::vector(ids.begin(), ids.end())).dispatch(); + MessageActivateTokens message(std::vector(ids.begin(), ids.end())); + message.isAggregation = true; + message.dispatch(); } else { - MessageActivateToken(getData()->getId()).dispatch(); + MessageActivateTokens message(getData()->getId()); + message.isEdge = true; + message.dispatch(); } } diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp index 4a2fd615..8a3d3d9b 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.cpp +++ b/src/app/qt/view/graphElements/QtGraphNode.cpp @@ -4,7 +4,7 @@ #include #include -#include "utility/messaging/type/MessageActivateToken.h" +#include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageGraphNodeMove.h" #include "qt/graphics/QtGraphicsRoundedRectItem.h" @@ -395,7 +395,7 @@ void QtGraphNode::onClick() { if (m_data && !m_data->isType(Node::NODE_UNDEFINED | Node::NODE_NAMESPACE)) { - MessageActivateToken(m_data->getId()).dispatch(); + MessageActivateTokens(m_data->getId()).dispatch(); } } diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 33081de3..fd311c65 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -7,7 +7,7 @@ #include "data/access/LocationAccessProxy.h" #include "utility/logging/logging.h" #include "utility/messaging/MessageQueue.h" -#include "utility/messaging/type/MessageActivateToken.h" +#include "utility/messaging/type/MessageActivateTokens.h" std::shared_ptr Application::create(ViewFactory* viewFactory) { @@ -48,7 +48,7 @@ void Application::loadProject(const std::string& projectSettingsFilePath) m_project->loadProjectSettings(projectSettingsFilePath); m_project->parseCode(); - MessageActivateToken(1).dispatch(); + activateInitialNode(); } void Application::loadSource(const std::string& sourceDirectoryPath) @@ -59,7 +59,7 @@ void Application::loadSource(const std::string& sourceDirectoryPath) m_project->setSourceDirectoryPath(sourceDirectoryPath); m_project->parseCode(); - MessageActivateToken(1).dispatch(); + activateInitialNode(); } void Application::reloadProject() @@ -67,7 +67,7 @@ void Application::reloadProject() m_project->clearStorage(); m_project->parseCode(); - MessageActivateToken(1).dispatch(); + activateInitialNode(); } void Application::saveProject(const std::string& projectSettingsFilePath) @@ -78,6 +78,18 @@ void Application::saveProject(const std::string& projectSettingsFilePath) } } +void Application::activateInitialNode() const +{ + Id mainId = m_graphAccessProxy->getIdForNodeWithName("main"); + + if (!mainId) + { + mainId = 1; + } + + MessageActivateTokens(mainId).dispatch(); +} + void Application::handleMessage(MessageLoadProject* message) { loadProject(message->projectSettingsFilePath); diff --git a/src/lib/Application.h b/src/lib/Application.h index b41088f2..6b66e2d0 100644 --- a/src/lib/Application.h +++ b/src/lib/Application.h @@ -35,6 +35,8 @@ public: private: Application(); + void activateInitialNode() const; + virtual void handleMessage(MessageLoadProject* message); virtual void handleMessage(MessageLoadSource* message); virtual void handleMessage(MessageRefresh* message); diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index f30f0f4f..b78d5871 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -194,7 +194,7 @@ add_files( utility/math/Vector4.h utility/math/VectorBase.h - utility/messaging/type/MessageActivateToken.h + utility/messaging/type/MessageActivateTokenLocation.h utility/messaging/type/MessageActivateTokens.h utility/messaging/type/MessageError.h utility/messaging/type/MessageFind.h diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 67b05eed..3a1a702a 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -1,6 +1,5 @@ #include "component/controller/CodeController.h" -#include "component/view/CodeView.h" #include "data/access/GraphAccess.h" #include "data/access/LocationAccess.h" #include "data/location/TokenLocation.h" @@ -8,8 +7,6 @@ #include "data/location/TokenLocationFile.h" #include "utility/text/TextAccess.h" -const uint CodeController::s_lineRadius = 2; - CodeController::CodeController(GraphAccess* graphAccess, LocationAccess* locationAccess) : m_graphAccess(graphAccess) , m_locationAccess(locationAccess) @@ -20,17 +17,64 @@ CodeController::~CodeController() { } -void CodeController::setActiveTokenIds(const std::vector& ids, Id activeId, Id declarationId) -{ - getView()->clearCodeSnippets(); - getView()->setActiveTokenIds(ids); +const uint CodeController::s_lineRadius = 2; +void CodeController::handleMessage(MessageActivateTokenLocation* message) +{ + if (message->locationId) + { + std::vector activeTokenIds = m_graphAccess->getActiveTokenIdsForLocationId(message->locationId); + MessageActivateTokens(activeTokenIds).dispatch(); + } +} + +void CodeController::handleMessage(MessageActivateTokens* message) +{ + std::vector activeTokenIds = message->tokenIds; + Id declarationId = 0; + + if (activeTokenIds.size() == 1) + { + activeTokenIds = m_graphAccess->getActiveTokenIdsForId(activeTokenIds[0], &declarationId); + } + + getView()->setActiveTokenIds(activeTokenIds); + getView()->showCodeSnippets(getSnippetsForActiveTokenIds(activeTokenIds, declarationId)); +} + +void CodeController::handleMessage(MessageRefresh* message) +{ + getView()->refreshView(); +} + +void CodeController::handleMessage(MessageShowFile* message) +{ + CodeView::CodeSnippetParams params; + params.startLineNumber = message->startLineNumber; + params.endLineNumber = message->endLineNumber; + + std::shared_ptr textAccess = TextAccess::createFromFile(message->filePath); + params.lineCount = textAccess->getLineCount(); + params.code = textAccess->getText(); + + params.locationFile = m_locationAccess->getTokenLocationsForFile(message->filePath); + + getView()->showCodeFile(params); +} + +CodeView* CodeController::getView() +{ + return Controller::getView(); +} + +std::vector CodeController::getSnippetsForActiveTokenIds( + const std::vector& ids, Id declarationId +) const { std::vector locationIds = m_graphAccess->getLocationIdsForTokenIds(ids); + TokenLocationCollection collection = m_locationAccess->getTokenLocationsForLocationIds(locationIds); std::vector snippets; - TokenLocationCollection collection = m_locationAccess->getTokenLocationsForLocationIds(locationIds); - collection.forEachTokenLocationFile( [&](TokenLocationFile* file) -> void { @@ -38,6 +82,7 @@ void CodeController::setActiveTokenIds(const std::vector& ids, Id activeId, std::shared_ptr textAccess = TextAccess::createFromFile(filePath); std::vector> ranges = getSnippetRangesForFile(file, s_lineRadius); + std::vector fileSnippets; for (const std::pair& range: ranges) { @@ -52,78 +97,40 @@ void CodeController::setActiveTokenIds(const std::vector& ids, Id activeId, params.startLineNumber = firstLineNumber; params.locationFile = - m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber); - params.locationFile.forEachTokenLocation( - [&](TokenLocation* location) - { - if(location->getTokenId() == activeId && activeId != 0) - { - params.isActive = true; - } - if(location->getTokenId() == declarationId && declarationId != 0) - { - params.isDeclaration = true; - } - } - ); + m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber); - snippets.push_back(params); + fileSnippets.push_back(params); } + + if (declarationId != 0) + { + bool isDeclarationFile = false; + for (const CodeView::CodeSnippetParams& snippet : fileSnippets) + { + snippet.locationFile.forEachTokenLocation( + [&](TokenLocation* location) + { + if (location->getTokenId() == declarationId) + { + isDeclarationFile = true; + } + } + ); + } + + for (CodeView::CodeSnippetParams& snippet : fileSnippets) + { + snippet.isDeclaration = isDeclarationFile; + } + } + + snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end()); } ); - + std::sort(snippets.begin(), snippets.end(), CodeView::CodeSnippetParams::sort); - for( CodeView::CodeSnippetParams p : snippets) - { - getView()->addCodeSnippet(p); - } -} - -void CodeController::handleMessage(MessageActivateToken* message) -{ - Id declarationId; - std::vector activeTokenIds = m_graphAccess->getActiveTokenIdsForId(message->tokenId, declarationId); - setActiveTokenIds(activeTokenIds, message->tokenId, declarationId); -} - -void CodeController::handleMessage(MessageActivateTokens* message) -{ - if (message->tokenIds.size () == 1) - { - Id declarationId; - std::vector activeTokenIds = m_graphAccess->getActiveTokenIdsForId(message->tokenIds[0], declarationId); - setActiveTokenIds(activeTokenIds, message->tokenIds[0], declarationId); - } - else - { - setActiveTokenIds(message->tokenIds, 0, 0); - } -} - -void CodeController::handleMessage(MessageRefresh* message) -{ - getView()->refreshView(); -} - -void CodeController::handleMessage(MessageShowFile* message) -{ - CodeView::CodeSnippetParams params; - params.startLineNumber = message->startLineNumber; - params.endLineNumber = message->endLineNumber; - getView()->setActiveTokenIds(message->activeTokenIds); - - std::shared_ptr textAccess = TextAccess::createFromFile(message->filePath); - params.lineCount = textAccess->getLineCount(); - params.code = textAccess->getText(); - - params.locationFile = m_locationAccess->getTokenLocationsForFile(message->filePath); - getView()->showCodeFile(params); -} - -CodeView* CodeController::getView() -{ - return Controller::getView(); + return snippets; } std::vector> CodeController::getSnippetRangesForFile( diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index f984dd16..fa1fc7b6 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -4,27 +4,21 @@ #include #include "component/controller/Controller.h" +#include "component/view/CodeView.h" #include "utility/messaging/MessageListener.h" -#include "utility/messaging/type/MessageActivateToken.h" +#include "utility/messaging/type/MessageActivateTokenLocation.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageRefresh.h" #include "utility/messaging/type/MessageShowFile.h" #include "utility/types.h" -class CodeView; class GraphAccess; class LocationAccess; class TokenLocationFile; -struct AnnotatedText -{ - std::string text; - Id tokenId; -}; - class CodeController : public Controller - , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -33,18 +27,18 @@ public: CodeController(GraphAccess* graphAccess, LocationAccess* locationAccess); ~CodeController(); - void setActiveTokenIds(const std::vector& ids, Id activeId, Id declarationId); - private: - virtual void handleMessage(MessageActivateToken* message); + static const uint s_lineRadius; + + virtual void handleMessage(MessageActivateTokenLocation* message); virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageRefresh* message); virtual void handleMessage(MessageShowFile* message); CodeView* getView(); - static const uint s_lineRadius; - + std::vector getSnippetsForActiveTokenIds( + const std::vector& ids, Id declarationId) const; std::vector> getSnippetRangesForFile(TokenLocationFile* file, const uint lineRadius) const; GraphAccess* m_graphAccess; diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 106d394c..357fe956 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -31,15 +31,29 @@ GraphController::~GraphController() { } -void GraphController::handleMessage(MessageActivateToken* message) -{ - std::vector activeTokenIds(1, message->tokenId); - createDummyGraphForTokenIds(activeTokenIds); -} - void GraphController::handleMessage(MessageActivateTokens* message) { - createDummyGraphForTokenIds(message->tokenIds); + if (message->isEdge && message->tokenIds.size() == 1) + { + m_currentActiveTokenIds = m_activeTokenIds; + m_currentActiveTokenIds.push_back(message->tokenIds[0]); + + setActiveAndVisibility(m_currentActiveTokenIds); + getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges); + return; + } + + if (message->isAggregation) + { + m_activeTokenIds.clear(); + m_currentActiveTokenIds = message->tokenIds; + + createDummyGraphForTokenIds(m_currentActiveTokenIds); + return; + } + + setActiveTokenIds(message->tokenIds); + createDummyGraphForTokenIds(m_activeTokenIds); } void GraphController::handleMessage(MessageGraphNodeExpand* message) @@ -49,7 +63,7 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message) { node->expanded = !node->expanded; - setActiveAndVisibility(m_activeTokenIds); + setActiveAndVisibility(m_currentActiveTokenIds); layoutNesting(); getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges); @@ -70,6 +84,12 @@ GraphView* GraphController::getView() const return Controller::getView(); } +void GraphController::setActiveTokenIds(const std::vector& activeTokenIds) +{ + m_activeTokenIds = activeTokenIds; + m_currentActiveTokenIds = activeTokenIds; +} + void GraphController::createDummyGraphForTokenIds(const std::vector& tokenIds) { const GraphLayouter::LayoutFunction layoutFunction = &GraphLayouter::layoutSimpleRaster; @@ -83,7 +103,6 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId std::shared_ptr graph = m_graphAccess->getGraphForActiveTokenIds(tokenIds); - m_dummyEdges.clear(); std::set addedNodes; @@ -106,7 +125,6 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId m_dummyNodes = dummyNodes; - m_activeTokenIds = tokenIds; setActiveAndVisibility(tokenIds); layoutNesting(); @@ -202,6 +220,7 @@ void GraphController::setActiveAndVisibility(const std::vector& activeTokenI for (DummyEdge& edge : m_dummyEdges) { edge.visible = true; + edge.active = false; if (find(activeTokenIds.begin(), activeTokenIds.end(), edge.data->getId()) != activeTokenIds.end()) { edge.active = true; @@ -244,7 +263,8 @@ void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode& node) const for (DummyNode& subNode : node.subNodes) { if (subNode.accessType != TokenComponentAccess::ACCESS_NONE || node.expanded || - (node.data && node.data->getType() == Node::NODE_ENUM)) + (node.data && node.data->isType(Node::NODE_ENUM)) || + (node.active && node.data && node.data->isType(Node::NODE_NAMESPACE | Node::NODE_UNDEFINED))) { setNodeVisibilityRecursiveTopDown(subNode); } diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index d1918b75..4b0c3e0d 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -4,7 +4,6 @@ #include #include "utility/messaging/MessageListener.h" -#include "utility/messaging/type/MessageActivateToken.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageGraphNodeExpand.h" #include "utility/messaging/type/MessageGraphNodeMove.h" @@ -21,7 +20,6 @@ class Node; class GraphController : public Controller - , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -48,13 +46,14 @@ public: ~GraphController(); private: - virtual void handleMessage(MessageActivateToken* message); virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageGraphNodeExpand* message); virtual void handleMessage(MessageGraphNodeMove* message); GraphView* getView() const; + void setActiveTokenIds(const std::vector& activeTokenIds); + void createDummyGraphForTokenIds(const std::vector& tokenIds); DummyNode createDummyNodeTopDown(Node* node); @@ -77,6 +76,7 @@ private: std::vector m_dummyEdges; std::vector m_activeTokenIds; + std::vector m_currentActiveTokenIds; }; #endif // GRAPH_CONTROLLER_H diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index 06d9bdaa..b65d62a0 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -5,7 +5,7 @@ SearchController::SearchController(GraphAccess* graphAccess) : m_graphAccess(graphAccess) - , m_ignoreNextMessageActivateToken(false) + , m_ignoreNextMessageActivateTokens(false) { } @@ -13,27 +13,18 @@ SearchController::~SearchController() { } -void SearchController::handleMessage(MessageActivateToken* message) +void SearchController::handleMessage(MessageActivateTokens* message) { - if (!m_ignoreNextMessageActivateToken && message->tokenId) + if (!m_ignoreNextMessageActivateTokens && message->tokenIds.size()) { SearchMatch match; - match.fullName = m_graphAccess->getNameForNodeWithId(message->tokenId); - match.tokenIds.insert(message->tokenId); + match.fullName = m_graphAccess->getNameForNodeWithId(message->tokenIds[0]); + match.tokenIds.insert(message->tokenIds[0]); getView()->setText(match.encodeForQuery()); } - m_ignoreNextMessageActivateToken = false; -} - -void SearchController::handleMessage(MessageActivateTokens* message) -{ - if (message->tokenIds.size()) - { - MessageActivateToken tokenMessage(message->tokenIds[0]); - handleMessage(&tokenMessage); - } + m_ignoreNextMessageActivateTokens = false; } void SearchController::handleMessage(MessageFind* message) @@ -52,7 +43,7 @@ void SearchController::handleMessage(MessageSearch* message) LOG_INFO("search string: \"" + query + "\""); - m_ignoreNextMessageActivateToken = true; + m_ignoreNextMessageActivateTokens = true; std::vector ids = m_graphAccess->getTokenIdsForQuery(query); if (!ids.size()) diff --git a/src/lib/component/controller/SearchController.h b/src/lib/component/controller/SearchController.h index 52a6c52c..5479c14d 100644 --- a/src/lib/component/controller/SearchController.h +++ b/src/lib/component/controller/SearchController.h @@ -5,7 +5,6 @@ #include "component/controller/Controller.h" #include "utility/messaging/MessageListener.h" -#include "utility/messaging/type/MessageActivateToken.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageFind.h" #include "utility/messaging/type/MessageRefresh.h" @@ -17,7 +16,6 @@ class SearchView; class SearchController : public Controller - , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -29,7 +27,6 @@ public: ~SearchController(); private: - virtual void handleMessage(MessageActivateToken* message); virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageFind* message); virtual void handleMessage(MessageRefresh* message); @@ -40,7 +37,7 @@ private: GraphAccess* m_graphAccess; - bool m_ignoreNextMessageActivateToken; + bool m_ignoreNextMessageActivateTokens; }; #endif // SEARCH_CONTROLLER_H diff --git a/src/lib/component/view/CodeView.cpp b/src/lib/component/view/CodeView.cpp index e656b8c9..253a33c8 100644 --- a/src/lib/component/view/CodeView.cpp +++ b/src/lib/component/view/CodeView.cpp @@ -13,23 +13,20 @@ CodeView::CodeSnippetParams::CodeSnippetParams() { } -bool CodeView::CodeSnippetParams::sort( CodeSnippetParams a, CodeSnippetParams b ) +bool CodeView::CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSnippetParams& b) { - if(a.isActive && b.isActive) - { - return false; - } // sort active snippet first - if(a.isActive) + if (a.isActive && !b.isActive) { return true; } - if(b.isActive) + else if (!a.isActive && b.isActive) { return false; } + // sort declarations - if(a.isDeclaration && !b.isDeclaration) + if (a.isDeclaration && !b.isDeclaration) { return true; } @@ -37,14 +34,16 @@ bool CodeView::CodeSnippetParams::sort( CodeSnippetParams a, CodeSnippetParams b { return false; } - else + + // different files + if (a.locationFile.getFilePath() != b.locationFile.getFilePath()) { // first header - if( FileSystem::filePathWithoutExtension(a.locationFile.getFilePath()) - == FileSystem::filePathWithoutExtension(b.locationFile.getFilePath()) ) + if (FileSystem::filePathWithoutExtension(a.locationFile.getFilePath()) == + FileSystem::filePathWithoutExtension(b.locationFile.getFilePath())) { - return FileSystem::extension(a.locationFile.getFilePath()) - > FileSystem::extension(b.locationFile.getFilePath()); + return FileSystem::extension(a.locationFile.getFilePath()) > + FileSystem::extension(b.locationFile.getFilePath()); } // alphabetical filepath without extension else @@ -53,6 +52,8 @@ bool CodeView::CodeSnippetParams::sort( CodeSnippetParams a, CodeSnippetParams b < FileSystem::filePathWithoutExtension(b.locationFile.getFilePath()); } } + + return a.startLineNumber < b.startLineNumber; } CodeView::CodeView(ViewLayout* viewLayout) diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 1dc48a2d..6f71b406 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -14,19 +14,19 @@ public: { CodeSnippetParams(); + // comparefunction for snippetsorting + static bool sort(const CodeSnippetParams& a, const CodeSnippetParams& b); + uint startLineNumber; uint endLineNumber; uint lineCount; std::string code; - TokenLocationFile locationFile; + TokenLocationFile locationFile; bool isActive; bool isDeclaration; - - //comparefunctions for snippetsorting - static bool sort(CodeSnippetParams a, CodeSnippetParams b); }; CodeView(ViewLayout* viewLayout); @@ -34,10 +34,10 @@ public: virtual std::string getName() const; - virtual void showCodeFile(const CodeSnippetParams& params) = 0; - virtual void addCodeSnippet(const CodeSnippetParams& params) = 0; virtual void clearCodeSnippets() = 0; - virtual void setActiveTokenIds(std::vector ids) = 0; + virtual void setActiveTokenIds(const std::vector& activeTokenIds) = 0; + virtual void showCodeSnippets(const std::vector& snippets) = 0; + virtual void showCodeFile(const CodeSnippetParams& params) = 0; private: CodeController* getController(); diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 1579976e..8e1c6d10 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -278,10 +278,11 @@ Id Storage::onCallParsed(const ParseLocation& location, const ParseVariable& cal return edge->getId(); } -Id Storage::onFieldUsageParsed( - const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy) -{ - log("field usage", user.getFullName() + " -> " + utility::join(usedNameHierarchy, "::"), location); +Id Storage::onVariableUsageParsed( + const std::string kind, const ParseLocation& location, const ParseFunction& user, + const std::vector& usedNameHierarchy +){ + log(kind, user.getFullName() + " -> " + utility::join(usedNameHierarchy, "::"), location); Node* userNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, user); Node* usedNode = addNodeHierarchy(Node::NODE_UNDEFINED_VARIABLE, usedNameHierarchy); @@ -292,12 +293,30 @@ Id Storage::onFieldUsageParsed( return edge->getId(); } +Id Storage::onFieldUsageParsed( + const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy +){ + return onVariableUsageParsed("field usage", location, user, usedNameHierarchy); +} + Id Storage::onGlobalVariableUsageParsed( // or static variable used + const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy +){ + return onVariableUsageParsed("global usage", location, user, usedNameHierarchy); +} + +Id Storage::onEnumFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy ){ - log("global usage", user.getFullName() + " -> " + utility::join(usedNameHierarchy, "::"), location); + return onVariableUsageParsed("enum field usage", location, user, usedNameHierarchy); +} - Node* userNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, user); +Id Storage::onEnumFieldUsageParsed( + const ParseLocation& location, const ParseVariable& user, const std::vector& usedNameHierarchy +){ + log("enum field usage", user.getFullName() + " -> " + utility::join(usedNameHierarchy, "::"), location); + + Node* userNode = addNodeHierarchy(Node::NODE_UNDEFINED_VARIABLE, user.nameHierarchy); Node* usedNode = addNodeHierarchy(Node::NODE_UNDEFINED_VARIABLE, usedNameHierarchy); Edge* edge = m_graph.createEdge(Edge::EDGE_USAGE, userNode, usedNode); @@ -322,6 +341,22 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& f return edge->getId(); } +Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) +{ + log("type usage", variable.getFullName() + " -> " + type.dataType.getRawTypeName(), type.location); + + Node* variableNode = addNodeHierarchy(Node::NODE_UNDEFINED, variable.nameHierarchy); + Edge* edge = addTypeEdge(variableNode, Edge::EDGE_TYPE_USAGE, type); + + if (!edge) + { + LOG_ERROR("Could not create type usage edge."); + return 0; + } + + return edge->getId(); +} + Id Storage::onTemplateRecordParameterTypeParsed( const ParseLocation& location, const std::string& templateParameterTypeName, const std::vector& templateRecordNameHierarchy @@ -466,13 +501,41 @@ std::shared_ptr Storage::getGraphForActiveTokenIds(const std::vector& { std::shared_ptr graph = std::make_shared(); - for (Id tokenId : tokenIds) + if (!tokenIds.size()) { - Token* token = m_graph.getTokenById(tokenId); + return graph; + } + + if (tokenIds.size() > 1) + { + for (Id tokenId : tokenIds) + { + Token* token = m_graph.getTokenById(tokenId); + if (!token) + { + LOG_ERROR_STREAM(<< "Token with id " << tokenId << " was not found"); + continue; + } + + if (token->isNode()) + { + Node* node = dynamic_cast(token); + graph->addNodeAndAllChildrenAsPlainCopy(node->getLastParentNode()); + } + else + { + Edge* edge = dynamic_cast(token); + graph->addEdgeAndAllChildrenAsPlainCopy(edge); + } + } + } + else if (tokenIds.size() == 1) + { + Token* token = m_graph.getTokenById(tokenIds[0]); if (!token) { - LOG_ERROR_STREAM(<< "Token with id " << tokenId << " was not found"); - continue; + LOG_ERROR_STREAM(<< "Token with id " << tokenIds[0] << " was not found"); + return graph; } if (token->isNode()) @@ -504,9 +567,10 @@ std::shared_ptr Storage::getGraphForActiveTokenIds(const std::vector& return graph; } -std::vector Storage::getActiveTokenIdsForId(Id tokenId, Id& declarationId) const +std::vector Storage::getActiveTokenIdsForId(Id tokenId, Id* declarationId) const { std::vector ret; + Token* token = m_graph.getTokenById(tokenId); if (!token) { @@ -516,30 +580,52 @@ std::vector Storage::getActiveTokenIdsForId(Id tokenId, Id& declarationId) c ret.push_back(token->getId()); Node* node; - if (token->isEdge()) + if (token->isNode()) { - node = dynamic_cast(token)->getTo(); - declarationId = node->getId(); + Node* node = dynamic_cast(token); + *declarationId = node->getId(); + + node->forEachEdge( + [&node, &ret](Edge* edge) + { + if (edge->getTo() == node) + { + ret.push_back(edge->getId()); + } + } + ); + } + + return ret; +} + +std::vector Storage::getActiveTokenIdsForLocationId(Id locationId) const +{ + std::vector ret; + + TokenLocation* location = m_locationCollection.findTokenLocationById(locationId); + if (!location) + { + return ret; + } + + Token* token = m_graph.getTokenById(location->getTokenId()); + if (!token) + { + return ret; + } + + if (token->isNode()) + { + Node* node = dynamic_cast(token); ret.push_back(node->getId()); } else { - node = dynamic_cast(token); - declarationId = node->getId(); + Edge* edge = dynamic_cast(token); + ret.push_back(edge->getTo()->getId()); } - //ret.push_back(node->getId()); - - node->forEachEdge( - [&node, &ret](Edge* e) - { - if (e->getTo() == node) - { - ret.push_back(e->getId()); - } - } - ); - return ret; } @@ -770,7 +856,15 @@ Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeU return nullptr; } - Node* typeNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, typeUsage.dataType.getTypeNameHierarchy()); + // FIXME: For some reason the TypeNameHierarchy is not always split up properly by the Parser. This might happen + // when a Type declaration is in a different file than it's usage, but this oberservation is not reliable. + std::vector nameHierarchy = typeUsage.dataType.getTypeNameHierarchy(); + if (nameHierarchy.size() == 1 && nameHierarchy[0].find('<') == std::string::npos) + { + nameHierarchy = utility::splitToVector(nameHierarchy[0], "::"); + } + + Node* typeNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, nameHierarchy); if (!typeNode) { return nullptr; diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index bf27490a..296ef8f8 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -62,11 +62,19 @@ public: const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee); virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee); + Id onVariableUsageParsed( + const std::string kind, const ParseLocation& location, const ParseFunction& user, + const std::vector& usedNameHierarchy); // helper virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy); virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy); + virtual Id onEnumFieldUsageParsed( + const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy); + virtual Id onEnumFieldUsageParsed( + const ParseLocation& location, const ParseVariable& user, const std::vector& usedNameHierarchy); virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function); + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable); virtual Id onTemplateRecordParameterTypeParsed( const ParseLocation& location, const std::string& templateParameterTypeName, @@ -87,7 +95,8 @@ public: virtual std::shared_ptr getGraphForActiveTokenIds(const std::vector& tokenIds) const; - virtual std::vector getActiveTokenIdsForId(Id tokenId, Id& declarationId) const; + virtual std::vector getActiveTokenIdsForId(Id tokenId, Id* declarationId) const; + virtual std::vector getActiveTokenIdsForLocationId(Id locationId) const; virtual std::vector getLocationIdsForTokenIds(const std::vector& tokenIds) const; virtual std::vector getTokenIdsForQuery(std::string query) const; @@ -105,8 +114,8 @@ protected: const SearchIndex& getSearchIndex() const; private: - Node* addNodeHierarchy(Node::NodeType type, std::vector nameHierarchy); + Node* addNodeHierarchy(Node::NodeType type, std::vector nameHierarchy); Node* addNodeHierarchyWithDistinctSignature(Node::NodeType type, const ParseFunction& function); TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const; diff --git a/src/lib/data/access/GraphAccess.h b/src/lib/data/access/GraphAccess.h index 10f60479..d0adb659 100644 --- a/src/lib/data/access/GraphAccess.h +++ b/src/lib/data/access/GraphAccess.h @@ -21,7 +21,8 @@ public: virtual std::shared_ptr getGraphForActiveTokenIds(const std::vector& tokenIds) const = 0; - virtual std::vector getActiveTokenIdsForId(Id tokenId, Id& declarationId) const = 0; + virtual std::vector getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0; + virtual std::vector getActiveTokenIdsForLocationId(Id locationId) const = 0; virtual std::vector getLocationIdsForTokenIds(const std::vector& tokenIds) const = 0; virtual std::vector getTokenIdsForQuery(std::string query) const = 0; diff --git a/src/lib/data/access/GraphAccessProxy.cpp b/src/lib/data/access/GraphAccessProxy.cpp index 4521afcc..29d468f7 100644 --- a/src/lib/data/access/GraphAccessProxy.cpp +++ b/src/lib/data/access/GraphAccessProxy.cpp @@ -69,7 +69,7 @@ std::shared_ptr GraphAccessProxy::getGraphForActiveTokenIds(const std::ve return std::make_shared(); } -std::vector GraphAccessProxy::getActiveTokenIdsForId(Id tokenId, Id& delcarationId) const +std::vector GraphAccessProxy::getActiveTokenIdsForId(Id tokenId, Id* delcarationId) const { if (hasSubject()) { @@ -79,6 +79,16 @@ std::vector GraphAccessProxy::getActiveTokenIdsForId(Id tokenId, Id& delcara return std::vector(); } +std::vector GraphAccessProxy::getActiveTokenIdsForLocationId(Id locationId) const +{ + if (hasSubject()) + { + return m_subject->getActiveTokenIdsForLocationId(locationId); + } + + return std::vector(); +} + std::vector GraphAccessProxy::getLocationIdsForTokenIds(const std::vector& tokenIds) const { if (hasSubject()) diff --git a/src/lib/data/access/GraphAccessProxy.h b/src/lib/data/access/GraphAccessProxy.h index 3b2968fb..311c6424 100644 --- a/src/lib/data/access/GraphAccessProxy.h +++ b/src/lib/data/access/GraphAccessProxy.h @@ -20,7 +20,8 @@ public: virtual std::shared_ptr getGraphForActiveTokenIds(const std::vector& tokenIds) const; - virtual std::vector getActiveTokenIdsForId(Id tokenId, Id& declarationId) const; + virtual std::vector getActiveTokenIdsForId(Id tokenId, Id* declarationId) const; + virtual std::vector getActiveTokenIdsForLocationId(Id locationId) const; virtual std::vector getLocationIdsForTokenIds(const std::vector& tokenIds) const; virtual std::vector getTokenIdsForQuery(std::string query) const; diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 466dcae5..4d0c51b7 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -88,7 +88,12 @@ public: const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy) = 0; virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy) = 0; + virtual Id onEnumFieldUsageParsed( + const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy) = 0; + virtual Id onEnumFieldUsageParsed( + const ParseLocation& location, const ParseVariable& user, const std::vector& usedNameHierarchy) = 0; virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0; + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) = 0; virtual Id onTemplateRecordParameterTypeParsed( const ParseLocation& location, const std::string& templateParameterTypeName, diff --git a/src/lib/data/parser/cxx/ASTBodyVisitor.cpp b/src/lib/data/parser/cxx/ASTBodyVisitor.cpp index 9d0d7fb0..2c4408e8 100644 --- a/src/lib/data/parser/cxx/ASTBodyVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTBodyVisitor.cpp @@ -62,6 +62,20 @@ void ASTBodyVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr* expr) VisitStmt(expr); } +void ASTBodyVisitor::VisitCXXNewExpr(clang::CXXNewExpr* expr) +{ + if (m_functionDecl) + { + m_client->VisitCXXNewExprInDeclBody(m_functionDecl, expr); + } + else + { + m_client->VisitCXXNewExprInDeclBody(m_varDecl, expr); + } + + VisitStmt(expr); +} + void ASTBodyVisitor::VisitMemberExpr(clang::make_ptr::type expr) { if (expr->getMemberDecl()->getKind() == clang::Decl::Kind::Field) @@ -75,7 +89,18 @@ void ASTBodyVisitor::VisitDeclRefExpr(clang::make_ptr::type { if (expr->getDecl()->getKind() == clang::Decl::Var && expr->getDecl()->isDefinedOutsideFunctionOrMethod()) { - m_client->VisitDeclRefExprInDeclBody(m_functionDecl, expr); + m_client->VisitGlobalVariableExprInDeclBody(m_functionDecl, expr); + } + else if (expr->getDecl()->getKind() == clang::Decl::EnumConstant) + { + if (m_functionDecl) + { + m_client->VisitEnumExprInDeclBody(m_functionDecl, expr); + } + else + { + m_client->VisitEnumExprInDeclBody(m_varDecl, expr); + } } VisitStmt(expr); } diff --git a/src/lib/data/parser/cxx/ASTBodyVisitor.h b/src/lib/data/parser/cxx/ASTBodyVisitor.h index 631febd1..22a15764 100644 --- a/src/lib/data/parser/cxx/ASTBodyVisitor.h +++ b/src/lib/data/parser/cxx/ASTBodyVisitor.h @@ -15,6 +15,7 @@ public: void VisitChildren(clang::Stmt* stmt); void VisitCallExpr(clang::CallExpr* expr); void VisitCXXConstructExpr(clang::CXXConstructExpr* expr); + void VisitCXXNewExpr(clang::CXXNewExpr* expr); void VisitMemberExpr(clang::make_ptr::type expr); void VisitDeclRefExpr(clang::make_ptr::type expr); void VisitDeclStmt(clang::DeclStmt* stmt); diff --git a/src/lib/data/parser/cxx/ASTBodyVisitorClient.h b/src/lib/data/parser/cxx/ASTBodyVisitorClient.h index bd71eeda..7743d5df 100644 --- a/src/lib/data/parser/cxx/ASTBodyVisitorClient.h +++ b/src/lib/data/parser/cxx/ASTBodyVisitorClient.h @@ -15,8 +15,12 @@ public: virtual void VisitCallExprInDeclBody(clang::VarDecl* decl, clang::CallExpr* expr) = 0; virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr) = 0; virtual void VisitCXXConstructExprInDeclBody(clang::VarDecl* decl, clang::CXXConstructExpr* expr) = 0; + virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr) = 0; + virtual void VisitCXXNewExprInDeclBody(clang::VarDecl* decl, clang::CXXNewExpr* expr) = 0; virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr) = 0; - virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0; + virtual void VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0; + virtual void VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0; + virtual void VisitEnumExprInDeclBody(clang::VarDecl* decl, clang::DeclRefExpr* expr) = 0; virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl) = 0; }; diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index dcf55889..e4e1065d 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -54,7 +54,19 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration) convertAccessType(declaration->getAccess()), getParseLocationOfRecordBody(declaration) ); + } + else if (declaration->isStruct()) + { + m_client->onStructParsed( + getParseLocationForNamedDecl(declaration), + utility::getDeclNameHierarchy(declaration), + convertAccessType(declaration->getAccess()), + getParseLocationOfRecordBody(declaration) + ); + } + if (declaration->isClass() || declaration->isStruct()) + { if (declaration->hasDefinition() && declaration->getNumBases()) { for (const clang::CXXBaseSpecifier& it : declaration->bases()) @@ -68,16 +80,6 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration) } } } - else if (declaration->isStruct()) - { - m_client->onStructParsed( - getParseLocationForNamedDecl(declaration), - utility::getDeclNameHierarchy(declaration), - convertAccessType(declaration->getAccess()), - getParseLocationOfRecordBody(declaration) - ); - // TODO: what about struct inheritance? - } } return true; @@ -438,6 +440,22 @@ void ASTVisitor::VisitCXXConstructExprInDeclBody(clang::VarDecl* decl, clang::CX ); } +void ASTVisitor::VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr) +{ + m_client->onTypeUsageParsed( + getParseTypeUsage(expr->getAllocatedTypeSourceInfo()->getTypeLoc(), expr->getAllocatedType()), + getParseFunction(decl) + ); +} + +void ASTVisitor::VisitCXXNewExprInDeclBody(clang::VarDecl* decl, clang::CXXNewExpr* expr) +{ + m_client->onTypeUsageParsed( + getParseTypeUsage(expr->getAllocatedTypeSourceInfo()->getTypeLoc(), expr->getAllocatedType()), + getParseVariable(decl) + ); +} + void ASTVisitor::VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr) { ParseLocation parseLocation = getParseLocation(expr->getSourceRange()); @@ -452,7 +470,7 @@ void ASTVisitor::VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::Mem ); } -void ASTVisitor::VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) +void ASTVisitor::VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) { ParseLocation parseLocation = getParseLocation(expr->getSourceRange()); @@ -466,6 +484,34 @@ void ASTVisitor::VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::De ); } +void ASTVisitor::VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) +{ + ParseLocation parseLocation = getParseLocation(expr->getSourceRange()); + + const std::string exprName = expr->getNameInfo().getAsString(); + parseLocation.endColumnNumber += exprName.size() - 1; + + m_client->onEnumFieldUsageParsed( + parseLocation, + getParseFunction(decl), + utility::getDeclNameHierarchy(expr->getDecl()) + ); +} + +void ASTVisitor::VisitEnumExprInDeclBody(clang::VarDecl* decl, clang::DeclRefExpr* expr) +{ + ParseLocation parseLocation = getParseLocation(expr->getSourceRange()); + + const std::string exprName = expr->getNameInfo().getAsString(); + parseLocation.endColumnNumber += exprName.size() - 1; + + m_client->onEnumFieldUsageParsed( + parseLocation, + getParseVariable(decl), + utility::getDeclNameHierarchy(expr->getDecl()) + ); +} + void ASTVisitor::VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl) { m_client->onTypeUsageParsed( @@ -480,12 +526,6 @@ bool ASTVisitor::hasValidLocation(const clang::Decl* declaration) const return location.isValid() && m_context->getSourceManager().isWrittenInMainFile(location); } -std::string ASTVisitor::getTypeName(const clang::QualType& qualType) const -{ - DataType dataType = utility::qualTypeToDataType(qualType); - return dataType.getRawTypeName(); -} - ParserClient::AccessType ASTVisitor::convertAccessType(clang::AccessSpecifier access) const { switch (access) diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h index 6df46e41..52e7a562 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.h +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -16,11 +16,11 @@ public: virtual ~ASTVisitor(); // Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file. - //virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl) - //{ - // decl->dump(); - // return true; - //} + // virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl) + // { + // decl->dump(); + // return true; + // } // RecursiveASTVisitor implementation virtual bool VisitStmt(const clang::Stmt* statement); // avoid visiting @@ -45,13 +45,16 @@ public: virtual void VisitCallExprInDeclBody(clang::VarDecl* decl, clang::CallExpr* expr); // calls in initialization of global variables virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr); // constructor calls virtual void VisitCXXConstructExprInDeclBody(clang::VarDecl* decl, clang::CXXConstructExpr* expr); // constructor calls of global variables + virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr); // type use of new operator + virtual void VisitCXXNewExprInDeclBody(clang::VarDecl* decl, clang::CXXNewExpr* expr); // type use of new operator in global space virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr); // field usages - virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // global variable usage + virtual void VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // global variable usage + virtual void VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // enum field usage + virtual void VisitEnumExprInDeclBody(clang::VarDecl* decl, clang::DeclRefExpr* expr); // enum field usage in global variable virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl); // type usages private: bool hasValidLocation(const clang::Decl* declaration) const; - std::string getTypeName(const clang::QualType& qualType) const; ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const; ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const; diff --git a/src/lib/data/type/DataType.cpp b/src/lib/data/type/DataType.cpp index 8345b3c4..3023fa84 100644 --- a/src/lib/data/type/DataType.cpp +++ b/src/lib/data/type/DataType.cpp @@ -47,7 +47,7 @@ std::string DataType::getRawTypeName() const return utility::join(m_typeNameHierarchy, "::"); } -std::vector DataType::getTypeNameHierarchy() const +const std::vector& DataType::getTypeNameHierarchy() const { return m_typeNameHierarchy; } diff --git a/src/lib/data/type/DataType.h b/src/lib/data/type/DataType.h index e12b35d4..27e7327e 100644 --- a/src/lib/data/type/DataType.h +++ b/src/lib/data/type/DataType.h @@ -23,7 +23,7 @@ public: std::string getFullTypeName() const; std::string getRawTypeName() const; - std::vector getTypeNameHierarchy() const; + const std::vector& getTypeNameHierarchy() const; private: const std::vector m_typeNameHierarchy; diff --git a/src/lib/utility/messaging/type/MessageActivateToken.h b/src/lib/utility/messaging/type/MessageActivateToken.h deleted file mode 100644 index 5f74068e..00000000 --- a/src/lib/utility/messaging/type/MessageActivateToken.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MESSAGE_ACTIVATE_TOKEN_H -#define MESSAGE_ACTIVATE_TOKEN_H - -#include "utility/messaging/Message.h" -#include "utility/types.h" - -class MessageActivateToken: public Message -{ -public: - MessageActivateToken(Id tokenId) - : tokenId(tokenId) - { - } - - static const std::string getStaticType() - { - return "MessageActivateToken"; - } - - const Id tokenId; -}; - -#endif // MESSAGE_ACTIVATE_TOKEN_H diff --git a/src/lib/utility/messaging/type/MessageActivateTokenLocation.h b/src/lib/utility/messaging/type/MessageActivateTokenLocation.h new file mode 100644 index 00000000..d534e7e5 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageActivateTokenLocation.h @@ -0,0 +1,23 @@ +#ifndef MESSAGE_ACTIVATE_TOKEN_LOCATION_H +#define MESSAGE_ACTIVATE_TOKEN_LOCATION_H + +#include "utility/messaging/Message.h" +#include "utility/types.h" + +class MessageActivateTokenLocation: public Message +{ +public: + MessageActivateTokenLocation(Id locationId) + : locationId(locationId) + { + } + + static const std::string getStaticType() + { + return "MessageActivateTokenLocation"; + } + + const Id locationId; +}; + +#endif // MESSAGE_ACTIVATE_TOKEN_LOCATION_H diff --git a/src/lib/utility/messaging/type/MessageActivateTokens.h b/src/lib/utility/messaging/type/MessageActivateTokens.h index 147a7370..53b222b3 100644 --- a/src/lib/utility/messaging/type/MessageActivateTokens.h +++ b/src/lib/utility/messaging/type/MessageActivateTokens.h @@ -9,6 +9,15 @@ class MessageActivateTokens: public Message public: MessageActivateTokens(const std::vector& tokenIds) : tokenIds(tokenIds) + , isEdge(false) + , isAggregation(false) + { + } + + MessageActivateTokens(Id tokenId) + : tokenIds(1, tokenId) + , isEdge(false) + , isAggregation(false) { } @@ -18,6 +27,9 @@ public: } const std::vector tokenIds; + + bool isEdge; + bool isAggregation; }; #endif // MESSAGE_ACTIVATE_TOKENS_H diff --git a/src/lib/utility/messaging/type/MessageShowFile.h b/src/lib/utility/messaging/type/MessageShowFile.h index f87bbb65..cf1c15ee 100644 --- a/src/lib/utility/messaging/type/MessageShowFile.h +++ b/src/lib/utility/messaging/type/MessageShowFile.h @@ -7,13 +7,10 @@ class MessageShowFile: public Message { public: - MessageShowFile( - const std::string& filePath, uint startLineNumber, uint endLineNumber, const std::vector& activeTokenIds - ) + MessageShowFile(const std::string& filePath, uint startLineNumber, uint endLineNumber) : filePath(filePath) , startLineNumber(startLineNumber) , endLineNumber(endLineNumber) - , activeTokenIds(activeTokenIds) { } @@ -25,7 +22,6 @@ public: const std::string filePath; const uint startLineNumber; const uint endLineNumber; - const std::vector activeTokenIds; }; #endif // MESSAGE_SHOW_FILE_H diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 8989e3dc..88d5ac1a 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -477,7 +477,18 @@ public: TS_ASSERT_EQUALS(client->globalVariables[0], "uint const * number <2:13 2:18>"); } - void test_cxx_parser_finds_public_inheritance() + void test_cxx_parser_finds_class_default_private_inheritance() + { + std::shared_ptr client = parseCode( + "class A {};\n" + "class B : A {};\n" + ); + + TS_ASSERT_EQUALS(client->inheritances.size(), 1); + TS_ASSERT_EQUALS(client->inheritances[0], "B : private A <2:11 2:11>"); + } + + void test_cxx_parser_finds_class_public_inheritance() { std::shared_ptr client = parseCode( "class A {};\n" @@ -488,7 +499,7 @@ public: TS_ASSERT_EQUALS(client->inheritances[0], "B : public A <2:11 2:18>"); } - void test_cxx_parser_finds_protected_inheritance() + void test_cxx_parser_finds_class_protected_inheritance() { std::shared_ptr client = parseCode( "class A {};\n" @@ -499,7 +510,7 @@ public: TS_ASSERT_EQUALS(client->inheritances[0], "B : protected A <2:11 2:21>"); } - void test_cxx_parser_finds_private_inheritance() + void test_cxx_parser_finds_class_private_inheritance() { std::shared_ptr client = parseCode( "class A {};\n" @@ -510,7 +521,7 @@ public: TS_ASSERT_EQUALS(client->inheritances[0], "B : private A <2:11 2:19>"); } - void test_cxx_parser_finds_multiple_inheritance() + void test_cxx_parser_finds_class_multiple_inheritance() { std::shared_ptr client = parseCode( "class A {};\n" @@ -526,6 +537,66 @@ public: TS_ASSERT_EQUALS(client->inheritances[1], "C : private B <5:4 5:12>"); } + void test_cxx_parser_finds_struct_default_public_inheritance() + { + std::shared_ptr client = parseCode( + "struct A {};\n" + "struct B : A {};\n" + ); + + TS_ASSERT_EQUALS(client->inheritances.size(), 1); + TS_ASSERT_EQUALS(client->inheritances[0], "B : public A <2:12 2:12>"); + } + + void test_cxx_parser_finds_struct_public_inheritance() + { + std::shared_ptr client = parseCode( + "struct A {};\n" + "struct B : public A {};\n" + ); + + TS_ASSERT_EQUALS(client->inheritances.size(), 1); + TS_ASSERT_EQUALS(client->inheritances[0], "B : public A <2:12 2:19>"); + } + + void test_cxx_parser_finds_struct_protected_inheritance() + { + std::shared_ptr client = parseCode( + "struct A {};\n" + "struct B : protected A {};\n" + ); + + TS_ASSERT_EQUALS(client->inheritances.size(), 1); + TS_ASSERT_EQUALS(client->inheritances[0], "B : protected A <2:12 2:22>"); + } + + void test_cxx_parser_finds_struct_private_inheritance() + { + std::shared_ptr client = parseCode( + "struct A {};\n" + "struct B : private A {};\n" + ); + + TS_ASSERT_EQUALS(client->inheritances.size(), 1); + TS_ASSERT_EQUALS(client->inheritances[0], "B : private A <2:12 2:20>"); + } + + void test_cxx_parser_finds_struct_multiple_inheritance() + { + std::shared_ptr client = parseCode( + "struct A {};\n" + "struct B {};\n" + "struct C\n" + " : public A\n" + " , private B\n" + "{};\n" + ); + + TS_ASSERT_EQUALS(client->inheritances.size(), 2); + TS_ASSERT_EQUALS(client->inheritances[0], "C : public A <4:4 4:11>"); + TS_ASSERT_EQUALS(client->inheritances[1], "C : private B <5:4 5:12>"); + } + void test_cxx_parser_finds_call_in_function() { std::shared_ptr client = parseCode( @@ -990,7 +1061,50 @@ public: TS_ASSERT_EQUALS(client->typeUses[1], "void B::B() -> A <8:8 8:8>"); } + void test_cxx_parser_finds_enum_uses_in_global_space() + { + std::shared_ptr client = parseCode( + "enum A\n" + "{\n" + " B,\n" + " C\n" + "};\n" + "A a = B;\n" + "A* aPtr = new A;\n" + ); + TS_ASSERT_EQUALS(client->usages.size(), 1); + TS_ASSERT_EQUALS(client->usages[0], "A a -> A::B <6:7 6:7>"); + TS_ASSERT_EQUALS(client->typeUses.size(), 1); + TS_ASSERT_EQUALS(client->typeUses[0], "A <7:15 7:15>"); + TS_ASSERT_EQUALS(client->globalVariables.size(), 2); + TS_ASSERT_EQUALS(client->globalVariables[0], "A a <6:3 6:3>"); + TS_ASSERT_EQUALS(client->globalVariables[1], "A * aPtr <7:4 7:7>"); + } + + void test_cxx_parser_finds_enum_uses_in_function_body() + { + std::shared_ptr client = parseCode( + "enum A\n" + "{\n" + " B,\n" + " C\n" + "};\n" + "int main()\n" + "{\n" + " A a = B;\n" + " A* aPtr = new A;\n" + "}\n" + ); + + TS_ASSERT_EQUALS(client->usages.size(), 1); + TS_ASSERT_EQUALS(client->usages[0], "int main() -> A::B <8:8 8:8>"); + TS_ASSERT_EQUALS(client->typeUses.size(), 4); + TS_ASSERT_EQUALS(client->typeUses[0], "int <6:1 6:3>"); + TS_ASSERT_EQUALS(client->typeUses[1], "int main() -> A <8:2 8:2>"); + TS_ASSERT_EQUALS(client->typeUses[2], "int main() -> A * <9:2 9:3>"); + TS_ASSERT_EQUALS(client->typeUses[3], "int main() -> A <9:16 9:16>"); + } void test_cxx_parser_finds_template_parameter_type_of_template_class() @@ -1430,12 +1544,32 @@ private: return 0; } + virtual Id onEnumFieldUsageParsed( + const ParseLocation& location, const ParseFunction& user, const std::vector& usedNameHierarchy) + { + usages.push_back(addLocationSuffix(functionStr(user) + " -> " + utility::join(usedNameHierarchy, "::"), location)); + return 0; + } + + virtual Id onEnumFieldUsageParsed( + const ParseLocation& location, const ParseVariable& user, const std::vector& usedNameHierarchy) + { + usages.push_back(addLocationSuffix(variableStr(user) + " -> " + utility::join(usedNameHierarchy, "::"), location)); + return 0; + } + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) { addTypeUse(type, function); return 0; } + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable) + { + addTypeUse(type); + return 0; + } + virtual Id onTemplateRecordParameterTypeParsed( const ParseLocation& location, const std::string& templateParameterTypeName, const std::vector& templateRecordNameHierarchy) diff --git a/src/test/StorageTestSuite.h b/src/test/StorageTestSuite.h index 219b42f2..09c79d3c 100644 --- a/src/test/StorageTestSuite.h +++ b/src/test/StorageTestSuite.h @@ -352,7 +352,7 @@ public: TS_ASSERT(isValidLocation(locations[0], 1)); } - void test_storage_saves_inheritance() + void test_storage_saves_class_inheritance() { TestStorage storage; storage.onClassParsed(validLocation(), utility::splitToVector("ClassA", "::"), ParserClient::ACCESS_NONE, validLocation()); @@ -377,6 +377,31 @@ public: TS_ASSERT(isValidLocation(locations[0], 5)); } + void test_storage_saves_struct_inheritance() + { + TestStorage storage; + storage.onStructParsed(validLocation(), utility::splitToVector("StructA", "::"), ParserClient::ACCESS_NONE, validLocation()); + storage.onStructParsed(validLocation(), utility::splitToVector("StructB", "::"), ParserClient::ACCESS_NONE, validLocation()); + Id id = + storage.onInheritanceParsed(validLocation(5), utility::splitToVector("StructB", "::"), + utility::splitToVector("StructA", "::"), ParserClient::ACCESS_PUBLIC + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_INHERITANCE); + + TS_ASSERT(edge->getComponent()); + TS_ASSERT_EQUALS(edge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PUBLIC); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "StructB"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "StructA"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 5)); + } + void test_storage_saves_call() { TestStorage storage;