logic: Show overview of analyzed symbols after launch

* show analysed nodes as bundles in graph
* ellide node names longer than 50 chars
* sort nodes alphabetic in these bundles
* show stats of analysis in code
* error are displayed as well in overview
* added keywords overview and error
* project description can be set in .coatiproject file
* description can include links to symbols using [symbol] syntax
* updated documentation
* increased toc nesting in documentation
This commit is contained in:
Eberhard Graether
2016-01-25 17:02:48 +01:00
parent 8addbb2195
commit ee5169274b
45 changed files with 752 additions and 223 deletions
@@ -7,6 +7,10 @@
<!-- COLOR: int int int int - rgba e.g. 125 125 125 255 -->
<config>
<info>
<description><!-- STRING: optional description shown in overview. Symbols can be linked with syntax [main] --></description>
</info>
<language_settings>
<language><!-- STRING: name of the language, e.g. c, c++, spanish, greek, greek++,... --></language>
<standard><!-- STRING: language version, e.g. c++ '11' --></standard>
@@ -1,12 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<config>
<source>
<extensions>
<header_extensions>.h</header_extensions>
<source_extensions>.cpp</source_extensions>
</extensions>
<source_paths>
<source_path>./src</source_path>
</source_paths>
</source>
</config>
<info>
<description>
This is the tutorial project of Coati.\nIt will introduce you to Coati's user interface.\nPlease click on the function [main] below to start the tutorial\n\n[main](); // &lt;- start here\n\n
</description>
</info>
<source>
<extensions>
<header_extensions>.h</header_extensions>
<source_extensions>.cpp</source_extensions>
</extensions>
<source_paths>
<source_path>./src</source_path>
</source_paths>
</source>
</config>
+1 -9
View File
@@ -3,7 +3,6 @@
#include "utility/logging/logging.h"
#include "utility/messaging/MessageQueue.h"
#include "utility/messaging/type/MessageActivateNodes.h"
#include "utility/messaging/type/MessageShowErrors.h"
#include "utility/messaging/type/MessageStatus.h"
#include "utility/scheduling/TaskScheduler.h"
#include "utility/Version.h"
@@ -130,14 +129,7 @@ void Application::handleMessage(MessageFinishedParsing* message)
{
m_project->logStats();
if (message->errorCount == 0)
{
MessageRefresh().refreshUiOnly().dispatch();
}
else
{
MessageShowErrors().dispatch();
}
MessageRefresh().refreshUiOnly().dispatch();
}
void Application::handleMessage(MessageLoadProject* message)
+3
View File
@@ -165,6 +165,7 @@ add_files(
data/StorageCache.cpp
data/StorageCache.h
data/StorageTypes.h
data/StorageStats.h
data/TaskCleanStorage.cpp
data/TaskCleanStorage.h
@@ -210,10 +211,12 @@ add_files(
utility/math/Vector4.h
utility/math/VectorBase.h
utility/messaging/type/MessageActivateAll.h
utility/messaging/type/MessageActivateEdge.h
utility/messaging/type/MessageActivateFile.h
utility/messaging/type/MessageActivateNodes.h
utility/messaging/type/MessageActivateTokenLocations.h
utility/messaging/type/MessageActivateTokenIds.h
utility/messaging/type/MessageActivateTokens.h
utility/messaging/type/MessageActivateWindow.h
utility/messaging/type/MessageAutoRefreshChanged.h
+129 -11
View File
@@ -5,6 +5,7 @@
#include "utility/messaging/type/MessageStatus.h"
#include "utility/text/TextAccess.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
#include "data/access/StorageAccess.h"
#include "data/location/TokenLocation.h"
@@ -12,6 +13,7 @@
#include "data/location/TokenLocationFile.h"
#include "data/location/TokenLocationLine.h"
#include "settings/ApplicationSettings.h"
#include "settings/ProjectSettings.h"
CodeController::CodeController(StorageAccess* storageAccess)
: m_storageAccess(storageAccess)
@@ -24,6 +26,63 @@ CodeController::~CodeController()
const uint CodeController::s_lineRadius = 2;
void CodeController::handleMessage(MessageActivateAll* message)
{
std::vector<std::string> errorMessages;
std::vector<CodeView::CodeSnippetParams> snippets = getSnippetsForErrorLocations(&errorMessages);
StorageStats stats = m_storageAccess->getStorageStats();
CodeView::CodeSnippetParams statsSnippet;
statsSnippet.startLineNumber = 1;
statsSnippet.endLineNumber = 1;
statsSnippet.locationFile = std::make_shared<TokenLocationFile>(FilePath());
statsSnippet.locationFile->isWholeCopy = true;
std::vector<std::string> description = getProjectDescription(statsSnippet.locationFile.get());
std::stringstream ss;
ss << "\n";
ss << "\t" + ProjectSettings::getInstance()->getFilePath().withoutExtension().fileName() + "\n";
if (description.size())
{
ss << "\n";
for (const std::string& line : description)
{
ss << line + "\n";
}
}
ss << "\n";
ss << "\t" + std::to_string(stats.fileCount) + " files\n";
ss << "\t" + std::to_string(stats.fileLOCCount) + " lines of code\n";
ss << "\n";
ss << "\t" + std::to_string(stats.nodeCount) + " symbols\n";
ss << "\t" + std::to_string(stats.edgeCount) + " relations\n";
ss << "\n";
ss << "\t" + std::to_string(stats.errorCount) + " errors\n";
ss << "\n";
if (stats.errorCount > 0)
{
ss << "\tWarning: The analysis may be incomplete as long as it yields errors.\n";
ss << "\tTry resolving them and refresh the project.\n";
ss << "\n";
}
statsSnippet.code = ss.str();
snippets.insert(snippets.begin(), statsSnippet);
CodeView* view = getView();
view->setActiveTokenIds(std::vector<Id>());
view->setErrorMessages(errorMessages);
view->showCodeSnippets(snippets);
}
void CodeController::handleMessage(MessageActivateTokens* message)
{
if (message->keepContent() && message->isIgnorable())
@@ -92,17 +151,7 @@ void CodeController::handleMessage(MessageFocusOut* message)
void CodeController::handleMessage(MessageShowErrors* message)
{
std::vector<std::string> errorMessages;
TokenLocationCollection errorCollection = m_storageAccess->getErrorTokenLocations(&errorMessages);
std::vector<CodeView::CodeSnippetParams> snippets;
errorCollection.forEachTokenLocationFile(
[&](std::shared_ptr<TokenLocationFile> file) -> void
{
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end());
}
);
std::vector<CodeView::CodeSnippetParams> snippets = getSnippetsForErrorLocations(&errorMessages);
CodeView* view = getView();
view->setActiveTokenIds(std::vector<Id>());
@@ -357,3 +406,72 @@ std::shared_ptr<SnippetMerger> CodeController::buildMergerHierarchy(
nextMerger->addChild(currentMerger);
return currentMerger;
}
std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForErrorLocations(
std::vector<std::string>* errorMessages)
const {
TokenLocationCollection errorCollection = m_storageAccess->getErrorTokenLocations(errorMessages);
std::vector<CodeView::CodeSnippetParams> snippets;
errorCollection.forEachTokenLocationFile(
[&](std::shared_ptr<TokenLocationFile> file) -> void
{
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end());
}
);
return snippets;
}
std::vector<std::string> CodeController::getProjectDescription(TokenLocationFile* locationFile) const
{
std::string description = ProjectSettings::getInstance()->getDescription();
if (!description.size())
{
return std::vector<std::string>();
}
std::vector<std::string> lines = utility::splitToVector(description, "\\n");
size_t startLineNumber = 4;
for (size_t i = 0; i < lines.size(); i++)
{
std::string line = "\t" + lines[i];
size_t pos = 0;
while (pos != std::string::npos)
{
size_t posA = line.find('[', pos);
size_t posB = line.find(']', posA);
if (posA == std::string::npos || posB == std::string::npos)
{
break;
}
std::string tokenName = line.substr(posA + 1, posB - posA - 1);
Id tokenId = m_storageAccess->getIdForNodeWithSearchNameHierarchy(NameHierarchy(tokenName));
if (tokenId > 0)
{
line.replace(posA, posB - posA + 1, tokenName);
locationFile->addTokenLocation(
0, tokenId,
startLineNumber + i, posA + 1,
startLineNumber + i, posA + tokenName.size()
);
}
pos = posA + tokenName.size();
}
lines[i] = line;
}
return lines;
}
@@ -5,6 +5,7 @@
#include <string>
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/MessageActivateAll.h"
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/messaging/type/MessageFocusIn.h"
#include "utility/messaging/type/MessageFocusOut.h"
@@ -24,6 +25,7 @@ class TokenLocationFile;
class CodeController
: public Controller
, public MessageListener<MessageActivateAll>
, public MessageListener<MessageActivateTokens>
, public MessageListener<MessageFocusIn>
, public MessageListener<MessageFocusOut>
@@ -39,6 +41,7 @@ public:
private:
static const uint s_lineRadius;
virtual void handleMessage(MessageActivateAll* message);
virtual void handleMessage(MessageActivateTokens* message);
virtual void handleMessage(MessageFocusIn* message);
virtual void handleMessage(MessageFocusOut* message);
@@ -57,6 +60,10 @@ private:
std::shared_ptr<SnippetMerger> buildMergerHierarchy(
TokenLocation* location, SnippetMerger& fileScopedMerger, std::map<int, std::shared_ptr<SnippetMerger>>& mergers) const;
std::vector<CodeView::CodeSnippetParams> getSnippetsForErrorLocations(std::vector<std::string>* errorMessages) const;
std::vector<std::string> getProjectDescription(TokenLocationFile* locationFile) const;
StorageAccess* m_storageAccess;
};
@@ -53,6 +53,15 @@ void FeatureController::handleMessage(MessageSearch* message)
}
}
void FeatureController::handleMessage(MessageActivateTokenIds* message)
{
std::shared_ptr<MessageActivateTokens> m = m_activationTranslator.translateMessage(message);
if (m)
{
m->dispatchImmediately();
}
}
void FeatureController::handleMessage(MessageActivateTokenLocations* message)
{
std::vector<Id> nodeIds = m_storageAccess->getNodeIdsForLocationIds(message->locationIds);
@@ -10,6 +10,7 @@
#include "utility/messaging/type/MessageActivateEdge.h"
#include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessageActivateNodes.h"
#include "utility/messaging/type/MessageActivateTokenIds.h"
#include "utility/messaging/type/MessageActivateTokenLocations.h"
#include "utility/messaging/type/MessageResetZoom.h"
#include "utility/messaging/type/MessageSearch.h"
@@ -23,6 +24,7 @@ class FeatureController
, public MessageListener<MessageActivateEdge>
, public MessageListener<MessageActivateFile>
, public MessageListener<MessageActivateNodes>
, public MessageListener<MessageActivateTokenIds>
, public MessageListener<MessageActivateTokenLocations>
, public MessageListener<MessageResetZoom>
, public MessageListener<MessageSearch>
@@ -38,6 +40,7 @@ private:
virtual void handleMessage(MessageActivateFile* message);
virtual void handleMessage(MessageActivateNodes* message);
virtual void handleMessage(MessageSearch* message);
virtual void handleMessage(MessageActivateTokenIds* message);
virtual void handleMessage(MessageActivateTokenLocations* message);
virtual void handleMessage(MessageResetZoom* message);
virtual void handleMessage(MessageSwitchColorScheme* message);
@@ -4,6 +4,7 @@
#include "utility/logging/logging.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
#include "component/controller/helper/DummyEdge.h"
#include "component/controller/helper/DummyNode.h"
@@ -23,6 +24,21 @@ GraphController::~GraphController()
{
}
void GraphController::handleMessage(MessageActivateAll* message)
{
m_activeNodeIds.clear();
m_activeEdgeIds.clear();
createDummyGraphForTokenIds(std::vector<Id>(), m_storageAccess->getGraphForAll());
bundleNodesByType();
layoutNesting();
layoutGraph();
buildGraph(message);
}
void GraphController::handleMessage(MessageActivateTokens* message)
{
if (message->isEdge || message->keepContent())
@@ -49,7 +65,16 @@ void GraphController::handleMessage(MessageActivateTokens* message)
return;
}
createDummyGraphForTokenIds(utility::concat(m_activeNodeIds, m_activeEdgeIds));
std::vector<Id> tokenIds = utility::concat(m_activeNodeIds, m_activeEdgeIds);
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForActiveTokenIds(tokenIds);
createDummyGraphForTokenIds(tokenIds, graph);
bundleNodes();
layoutNesting();
layoutGraph();
buildGraph(message);
}
@@ -76,7 +101,7 @@ void GraphController::handleMessage(MessageGraphNodeBundleSplit* message)
DummyNode& node = m_dummyNodes[i];
if (node.isBundleNode() && node.tokenId == message->bundleId)
{
m_dummyNodes.insert(m_dummyNodes.end(), node.bundledNodes.begin(), node.bundledNodes.end());
m_dummyNodes.insert(m_dummyNodes.begin() + i + 1, node.bundledNodes.begin(), node.bundledNodes.end());
m_dummyNodes.erase(m_dummyNodes.begin() + i);
break;
}
@@ -156,7 +181,7 @@ void GraphController::clear()
getView()->clear();
}
void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenIds)
void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenIds, const std::shared_ptr<Graph> graph)
{
GraphView* view = getView();
if (!view)
@@ -165,8 +190,6 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
return;
}
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForActiveTokenIds(tokenIds);
m_dummyEdges.clear();
std::set<Id> addedNodes;
@@ -190,6 +213,7 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
for (DummyNode& node : dummyNodes)
{
node.hasParent = false;
node.name = node.data->getFullName();
}
m_dummyNodes = dummyNodes;
@@ -197,11 +221,6 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
autoExpandActiveNode(tokenIds);
setActiveAndVisibility(tokenIds);
bundleNodes();
layoutNesting();
layoutGraph();
m_graph = graph;
}
@@ -210,6 +229,7 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
DummyNode result;
result.data = node;
result.tokenId = node->getId();
result.name = node->getName();
// there is a global root node with id 0 afaik, so here we actually want the one node below this global root
Node* parent = node;
@@ -314,6 +334,8 @@ void GraphController::autoExpandActiveNode(const std::vector<Id>& activeTokenIds
void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenIds)
{
bool noActive = activeTokenIds.size() == 0;
for (DummyNode& node : m_dummyNodes)
{
setNodeActiveRecursive(node, activeTokenIds);
@@ -335,7 +357,7 @@ void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenI
DummyNode* from = findDummyNodeRecursive(m_dummyNodes, edge.ownerId);
DummyNode* to = findDummyNodeRecursive(m_dummyNodes, edge.targetId);
if (from && to && (from->active || to->active || edge.active))
if (from && to && (noActive || from->active || to->active || edge.active))
{
edge.visible = true;
from->connected = true;
@@ -345,7 +367,7 @@ void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenI
for (DummyNode& node : m_dummyNodes)
{
setNodeVisibilityRecursiveBottomUp(node);
setNodeVisibilityRecursiveBottomUp(node, noActive);
}
}
@@ -364,7 +386,7 @@ void GraphController::setNodeActiveRecursive(DummyNode& node, const std::vector<
}
}
bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode& node) const
bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode& node, bool noActive) const
{
node.visible = false;
node.childVisible = false;
@@ -382,13 +404,13 @@ bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode& node) const
for (DummyNode& subNode : node.subNodes)
{
if (setNodeVisibilityRecursiveBottomUp(subNode))
if (setNodeVisibilityRecursiveBottomUp(subNode, noActive))
{
node.childVisible = true;
}
}
if (node.active || node.connected || node.childVisible)
if (noActive || node.active || node.connected || node.childVisible)
{
setNodeVisibilityRecursiveTopDown(node, false);
}
@@ -617,6 +639,54 @@ bool GraphController::isTypeNodeWithSingleInheritance(const DummyNode& node, boo
return matches;
}
#define BUNDLE_BY_TYPE(__type__, __name__) \
bundleNodesMatching( \
[&](const DummyNode& node) \
{ \
return node.visible && node.isGraphNode() && node.data->isType(__type__); \
}, \
1, \
__name__ \
); \
void GraphController::bundleNodesByType()
{
BUNDLE_BY_TYPE(Node::NODE_CLASS, "Classes");
BUNDLE_BY_TYPE(Node::NODE_STRUCT, "Structs");
BUNDLE_BY_TYPE(Node::NODE_FUNCTION, "Functions");
BUNDLE_BY_TYPE(Node::NODE_GLOBAL_VARIABLE, "Global Variables");
BUNDLE_BY_TYPE(Node::NODE_TYPE, "Types");
BUNDLE_BY_TYPE(Node::NODE_TYPEDEF, "Typedefs");
BUNDLE_BY_TYPE(Node::NODE_ENUM, "Enums");
BUNDLE_BY_TYPE(Node::NODE_FILE, "Files");
BUNDLE_BY_TYPE(Node::NODE_MACRO, "Macros");
// should never be visible
BUNDLE_BY_TYPE(Node::NODE_METHOD, "Methods");
BUNDLE_BY_TYPE(Node::NODE_FIELD, "Fields");
BUNDLE_BY_TYPE(Node::NODE_ENUM_CONSTANT, "Enum Constants");
BUNDLE_BY_TYPE(Node::NODE_TEMPLATE_PARAMETER_TYPE, "Template Parameter Types");
BUNDLE_BY_TYPE(Node::NODE_UNDEFINED, "Undefined Symbols");
BUNDLE_BY_TYPE(Node::NODE_NAMESPACE, "Namespaces");
for (DummyNode& node : m_dummyNodes)
{
if (node.isBundleNode())
{
sort(node.bundledNodes.begin(), node.bundledNodes.end(),
[](const DummyNode& a, const DummyNode& b) -> bool
{
return utility::toLowerCase(a.name) < utility::toLowerCase(b.name);
}
);
}
}
}
void GraphController::layoutNesting()
{
for (DummyNode& node : m_dummyNodes)
@@ -663,15 +733,14 @@ void GraphController::layoutNestingRecursive(DummyNode& node) const
if (node.isGraphNode())
{
if (!node.hasParent)
size_t maxNameSize = 50;
if (!node.active && node.name.size() > maxNameSize)
{
width = margins.charWidth * node.data->getFullName().size();
}
else
{
width = margins.charWidth * node.data->getName().size();
node.name = node.name.substr(0, maxNameSize - 3) + "...";
}
width = margins.charWidth * node.name.size();
if (node.data->isType(Node::NODE_TYPE | Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM) && node.subNodes.size())
{
addExpandToggleNode(node);
@@ -4,6 +4,7 @@
#include <vector>
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/MessageActivateAll.h"
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/messaging/type/MessageFlushUpdates.h"
#include "utility/messaging/type/MessageFocusIn.h"
@@ -26,6 +27,7 @@ class StorageAccess;
class GraphController
: public Controller
, public MessageListener<MessageActivateAll>
, public MessageListener<MessageActivateTokens>
, public MessageListener<MessageFlushUpdates>
, public MessageListener<MessageFocusIn>
@@ -40,6 +42,7 @@ public:
~GraphController();
private:
virtual void handleMessage(MessageActivateAll* message);
virtual void handleMessage(MessageActivateTokens* message);
virtual void handleMessage(MessageFlushUpdates* message);
virtual void handleMessage(MessageFocusIn* message);
@@ -53,20 +56,21 @@ private:
void clear();
void createDummyGraphForTokenIds(const std::vector<Id>& tokenIds);
void createDummyGraphForTokenIds(const std::vector<Id>& tokenIds, const std::shared_ptr<Graph> graph);
DummyNode createDummyNodeTopDown(Node* node);
void autoExpandActiveNode(const std::vector<Id>& activeTokenIds);
void setActiveAndVisibility(const std::vector<Id>& activeTokenIds);
void setNodeActiveRecursive(DummyNode& node, const std::vector<Id>& activeTokenIds) const;
bool setNodeVisibilityRecursiveBottomUp(DummyNode& node) const;
bool setNodeVisibilityRecursiveBottomUp(DummyNode& node, bool noActive) const;
void setNodeVisibilityRecursiveTopDown(DummyNode& node, bool parentExpanded) const;
void bundleNodes();
void bundleNodesMatching(std::function<bool(const DummyNode&)> matcher, size_t count, const std::string& name);
bool isTypeNodeWithSingleAggregation(const DummyNode& node, TokenComponentAggregation::Direction direction) const;
bool isTypeNodeWithSingleInheritance(const DummyNode& node, bool isBase) const;
void bundleNodesByType();
void layoutNesting();
void layoutNestingRecursive(DummyNode& node) const;
@@ -12,6 +12,12 @@ SearchController::~SearchController()
{
}
void SearchController::handleMessage(MessageActivateAll* message)
{
SearchMatch match = SearchMatch::createCommand(SearchMatch::COMMAND_ALL);
getView()->setMatches(std::vector<SearchMatch>(1, match));
}
void SearchController::handleMessage(MessageActivateTokens* message)
{
if (!message->keepContent() && !message->isFromSearch)
@@ -33,7 +39,8 @@ void SearchController::handleMessage(MessageSearchAutocomplete* message)
void SearchController::handleMessage(MessageShowErrors* message)
{
getView()->setMatches(std::vector<SearchMatch>());
SearchMatch match = SearchMatch::createCommand(SearchMatch::COMMAND_ERROR);
getView()->setMatches(std::vector<SearchMatch>(1, match));
}
SearchView* SearchController::getView()
@@ -3,6 +3,7 @@
#include "component/controller/Controller.h"
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/MessageActivateAll.h"
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/messaging/type/MessageFind.h"
#include "utility/messaging/type/MessageSearchAutocomplete.h"
@@ -13,6 +14,7 @@ class SearchView;
class SearchController
: public Controller
, public MessageListener<MessageActivateAll>
, public MessageListener<MessageActivateTokens>
, public MessageListener<MessageFind>
, public MessageListener<MessageSearchAutocomplete>
@@ -23,6 +25,7 @@ public:
~SearchController();
private:
virtual void handleMessage(MessageActivateAll* message);
virtual void handleMessage(MessageActivateTokens* message);
virtual void handleMessage(MessageFind* message);
virtual void handleMessage(MessageSearchAutocomplete* message);
@@ -67,6 +67,18 @@ void UndoRedoController::handleMessage(MessageActivateNodes* message)
processCommand(command);
}
void UndoRedoController::handleMessage(MessageActivateTokenIds* message)
{
if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType() && message->tokenIds.size() &&
static_cast<MessageActivateTokenIds*>(m_lastCommand.message.get())->tokenIds == message->tokenIds)
{
return;
}
Command command(std::make_shared<MessageActivateTokenIds>(*message), 0);
processCommand(command);
}
void UndoRedoController::handleMessage(MessageDeactivateEdge* message)
{
MessageBase* m = nullptr;
@@ -140,23 +152,9 @@ void UndoRedoController::handleMessage(MessageRefresh* message)
if (requiresActivateFallbackToken())
{
Id nodeId = m_storageAccess->getIdForNodeWithSearchNameHierarchy(NameHierarchy("main"));
if (!nodeId)
{
nodeId = m_storageAccess->getIdForFirstNode();
}
if (nodeId)
{
MessageActivateNodes m;
m.addNode(
nodeId,
m_storageAccess->getNodeTypeForNodeWithId(nodeId),
m_storageAccess->getNameHierarchyForNodeWithId(nodeId)
);
m.isFromSystem = true;
m.dispatch();
}
SearchMatch match = SearchMatch::createCommand(SearchMatch::COMMAND_ALL);
MessageSearch msg(std::vector<SearchMatch>(1, match));
msg.dispatch();
}
else
{
@@ -8,6 +8,7 @@
#include "utility/messaging/type/MessageActivateEdge.h"
#include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessageActivateNodes.h"
#include "utility/messaging/type/MessageActivateTokenIds.h"
#include "utility/messaging/type/MessageDeactivateEdge.h"
#include "utility/messaging/type/MessageGraphNodeBundleSplit.h"
#include "utility/messaging/type/MessageGraphNodeExpand.h"
@@ -32,6 +33,7 @@ class UndoRedoController
, public MessageListener<MessageActivateEdge>
, public MessageListener<MessageActivateFile>
, public MessageListener<MessageActivateNodes>
, public MessageListener<MessageActivateTokenIds>
, public MessageListener<MessageDeactivateEdge>
, public MessageListener<MessageGraphNodeBundleSplit>
, public MessageListener<MessageGraphNodeExpand>
@@ -63,6 +65,7 @@ private:
virtual void handleMessage(MessageActivateEdge* message);
virtual void handleMessage(MessageActivateFile* message);
virtual void handleMessage(MessageActivateNodes* message);
virtual void handleMessage(MessageActivateTokenIds* message);
virtual void handleMessage(MessageDeactivateEdge* message);
virtual void handleMessage(MessageGraphNodeBundleSplit* message);
virtual void handleMessage(MessageGraphNodeExpand* message);
@@ -1,11 +1,14 @@
#include "component/controller/helper/ActivationTranslator.h"
#include "data/access/StorageAccess.h"
#include "utility/messaging/type/MessageActivateAll.h"
#include "utility/messaging/type/MessageActivateEdge.h"
#include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessageActivateNodes.h"
#include "utility/messaging/type/MessageActivateTokenIds.h"
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/messaging/type/MessageSearch.h"
#include "utility/messaging/type/MessageShowErrors.h"
#include "utility/messaging/type/MessageShowFile.h"
ActivationTranslator::ActivationTranslator(StorageAccess* storageAccess)
@@ -99,9 +102,40 @@ std::shared_ptr<MessageActivateTokens> ActivationTranslator::translateMessage(co
return m;
}
std::shared_ptr<MessageActivateTokens> ActivationTranslator::translateMessage(const MessageActivateTokenIds* message) const
{
std::shared_ptr<MessageActivateTokens> m;
m = std::make_shared<MessageActivateTokens>(message->tokenIds);
m->undoRedoType = message->undoRedoType;
m->setKeepContent(message->keepContent());
return m;
}
std::shared_ptr<MessageActivateTokens> ActivationTranslator::translateMessage(const MessageSearch* message) const
{
std::vector<Id> tokenIds = m_storageAccess->getTokenIdsForMatches(message->getMatches());
const std::vector<SearchMatch>& matches = message->getMatches();
for (const SearchMatch& match : matches)
{
if (match.searchType == SearchMatch::SEARCH_COMMAND &&
match.getFullName() == SearchMatch::getCommandName(SearchMatch::COMMAND_ALL))
{
MessageActivateAll msg;
msg.undoRedoType = message->undoRedoType;
msg.dispatchImmediately();
return nullptr;
}
else if (match.searchType == SearchMatch::SEARCH_COMMAND &&
match.getFullName() == SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR))
{
MessageShowErrors msg;
msg.undoRedoType = message->undoRedoType;
msg.dispatchImmediately();
return nullptr;
}
}
std::vector<Id> tokenIds = m_storageAccess->getTokenIdsForMatches(matches);
tokenIds = m_storageAccess->getActiveTokenIdsForTokenIds(tokenIds);
std::shared_ptr<MessageActivateTokens> m;
@@ -6,6 +6,7 @@
class MessageActivateEdge;
class MessageActivateFile;
class MessageActivateNodes;
class MessageActivateTokenIds;
class MessageActivateTokens;
class MessageSearch;
class StorageAccess;
@@ -19,6 +20,7 @@ public:
std::shared_ptr<MessageActivateTokens> translateMessage(const MessageActivateEdge* message) const;
std::shared_ptr<MessageActivateTokens> translateMessage(const MessageActivateFile* message) const;
std::shared_ptr<MessageActivateTokens> translateMessage(const MessageActivateNodes* message) const;
std::shared_ptr<MessageActivateTokens> translateMessage(const MessageActivateTokenIds* message) const;
std::shared_ptr<MessageActivateTokens> translateMessage(const MessageSearch* message) const;
private:
@@ -126,13 +126,18 @@ void BucketGrid::createBuckets(std::vector<DummyNode>& nodes, const std::vector<
bool activeNodeAdded = false;
for (DummyNode& node : nodes)
{
if (node.hasActiveSubNode())
if (node.hasActiveSubNode() || !edges.size())
{
addNode(&node);
activeNodeAdded = true;
}
}
if (!edges.size())
{
return;
}
if (!activeNodeAdded)
{
addNode(&nodes[0]);
@@ -114,6 +114,8 @@ public:
// GraphNode
const Node* data;
std::string name;
bool active;
bool connected;
bool expanded;
@@ -127,7 +129,6 @@ public:
// BundleNode
std::vector<DummyNode> bundledNodes;
std::string name;
};
#endif // DUMMY_NODE_H
+21
View File
@@ -135,6 +135,27 @@ void HierarchyCache::addFirstVisibleChildIdsForNodeId(Id nodeId, std::vector<Id>
}
}
bool HierarchyCache::isChildOfVisibleNodeOrInvisible(Id nodeId) const
{
HierarchyNode* node = getNode(nodeId);
if (!node)
{
return false;
}
if (!node->isVisible())
{
return true;
}
if (node->getParent() && node->getParent()->isVisible())
{
return true;
}
return false;
}
HierarchyCache::HierarchyNode* HierarchyCache::getNode(Id nodeId) const
{
std::map<Id, std::shared_ptr<HierarchyNode>>::const_iterator it = m_nodes.find(nodeId);
+2
View File
@@ -19,6 +19,8 @@ public:
void addAllChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const;
void addFirstVisibleChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds) const;
bool isChildOfVisibleNodeOrInvisible(Id nodeId) const;
private:
class HierarchyNode
{
+9 -2
View File
@@ -119,10 +119,11 @@ Id SqliteStorage::addFile(const std::string& serializedName, const std::string&
{
Id id = addNode(Node::NODE_FILE, serializedName, true);
std::shared_ptr<TextAccess> content = TextAccess::createFromFile(filePath);
unsigned int loc = content->getLineCount();
CppSQLite3Statement stmt = m_database.compileStatement((
"INSERT INTO file(id, path, modification_time, content) VALUES("
+ std::to_string(id) + ", '" + filePath + "', '" + modificationTime + "', ?);"
"INSERT INTO file(id, path, modification_time, content, loc) VALUES("
+ std::to_string(id) + ", '" + filePath + "', '" + modificationTime + "', ?, " + std::to_string(loc) + ");"
).c_str());
stmt.bind(1, content->getText().c_str());
@@ -653,6 +654,11 @@ int SqliteStorage::getFileCount() const
return m_database.execScalar("SELECT COUNT(*) FROM file;");
}
int SqliteStorage::getFileLOCCount() const
{
return m_database.execScalar("SELECT SUM(loc) FROM file;");
}
int SqliteStorage::getSourceLocationCount() const
{
return m_database.execScalar("SELECT COUNT(*) FROM source_location;");
@@ -719,6 +725,7 @@ void SqliteStorage::setupTables()
"path TEXT, "
"modification_time TEXT, "
"content TEXT, "
"loc INTEGER, "
"PRIMARY KEY(id), "
"FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);"
);
+1
View File
@@ -98,6 +98,7 @@ public:
int getNodeCount() const;
int getEdgeCount() const;
int getFileCount() const;
int getFileLOCCount() const;
int getSourceLocationCount() const;
private:
+58 -8
View File
@@ -40,6 +40,9 @@ Version Storage::getVersion() const
bool Storage::init()
{
m_commandIndex.addNode(NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)));
m_commandIndex.addNode(NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)));
return m_sqliteStorage.init();
}
@@ -141,19 +144,21 @@ const SearchIndex& Storage::getSearchIndex() const
void Storage::logStats() const
{
std::stringstream ss;
StorageStats stats = getStorageStats();
ss << "\nGraph:\n";
ss << "\t" << m_sqliteStorage.getNodeCount() << " Nodes\n";
ss << "\t" << m_sqliteStorage.getEdgeCount() << " Edges\n";
ss << "\t" << stats.nodeCount << " Nodes\n";
ss << "\t" << stats.edgeCount << " Edges\n";
ss << "\nSearch:\n";
ss << "\t" << m_tokenIndex.getCharCount() << " Characters\n";
ss << "\t" << m_tokenIndex.getWordCount() << " Words\n";
ss << "\t" << m_tokenIndex.getNodeCount() << " SearchNodes\n";
ss << "\t" << stats.charCount << " Characters\n";
ss << "\t" << stats.wordCount << " Words\n";
ss << "\t" << stats.searchNodeCount << " SearchNodes\n";
ss << "\nCode:\n";
ss << "\t" << m_sqliteStorage.getFileCount() << " Files\n";
ss << "\t" << m_sqliteStorage.getSourceLocationCount() << " Source Locations\n";
ss << "\t" << stats.fileCount << " Files\n";
ss << "\t" << stats.fileLOCCount << " Lines of Code\n";
ss << "\t" << stats.sourceLocationCount << " Source Locations\n";
LOG_WARNING(ss.str());
}
@@ -812,7 +817,12 @@ std::vector<SearchMatch> Storage::getAutocompletionMatches(const std::string& qu
m_cachedQuery = query;
std::vector<SearchMatch> matches = SearchIndex::getMatches(m_cachedResults, query);
SearchResults results = m_cachedResults;
SearchResults commandResults = m_commandIndex.runFuzzySearch(query);
results.insert(commandResults.begin(), commandResults.end());
std::vector<SearchMatch> matches = SearchIndex::getMatches(results, query);
LOG_INFO_STREAM(<< matches.size() << " matches for \"" << query << "\"");
if (matches.size() > 100)
@@ -825,6 +835,7 @@ std::vector<SearchMatch> Storage::getAutocompletionMatches(const std::string& qu
if (!match.tokenIds.size())
{
match.searchType = SearchMatch::SEARCH_COMMAND;
match.typeName = "command";
continue;
}
@@ -883,6 +894,25 @@ std::vector<SearchMatch> Storage::getSearchMatchesForTokenIds(const std::vector<
return matches;
}
std::shared_ptr<Graph> Storage::getGraphForAll() const
{
std::shared_ptr<Graph> graph = std::make_shared<Graph>();
std::vector<Id> tokenIds;
for (StorageNode node: m_sqliteStorage.getAllNodes())
{
if (node.defined && Node::intToType(node.type) != Node::NODE_TEMPLATE_PARAMETER_TYPE
&& !m_hierarchyCache.isChildOfVisibleNodeOrInvisible(node.id))
{
tokenIds.push_back(node.id);
}
}
addNodesToGraph(tokenIds, graph.get());
return graph;
}
std::shared_ptr<Graph> Storage::getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const
{
std::shared_ptr<Graph> g = std::make_shared<Graph>();
@@ -1293,6 +1323,26 @@ TimePoint Storage::getFileModificationTime(const FilePath& filePath) const
return TimePoint(m_sqliteStorage.getFileByPath(filePath.str()).modificationTime);
}
StorageStats Storage::getStorageStats() const
{
StorageStats stats;
stats.nodeCount = m_sqliteStorage.getNodeCount();
stats.edgeCount = m_sqliteStorage.getEdgeCount();
stats.charCount = m_tokenIndex.getCharCount();
stats.wordCount = m_tokenIndex.getWordCount();
stats.searchNodeCount = m_tokenIndex.getNodeCount();
stats.fileCount = m_sqliteStorage.getFileCount();
stats.fileLOCCount = m_sqliteStorage.getFileLOCCount();
stats.sourceLocationCount = m_sqliteStorage.getSourceLocationCount();
stats.errorCount = getErrorCount();
return stats;
}
Id Storage::addNodeHierarchy(Node::NodeType nodeType, NameHierarchy nameHierarchy, bool defined)
{
if (nameHierarchy.size() == 0)
+5
View File
@@ -146,6 +146,7 @@ public:
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::string& query) const;
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const;
virtual std::shared_ptr<Graph> getGraphForAll() const;
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const;
virtual std::vector<Id> getActiveTokenIdsForTokenIds(const std::vector<Id>& tokenIds) const;
@@ -171,6 +172,8 @@ public:
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const;
virtual TimePoint getFileModificationTime(const FilePath& filePath) const;
virtual StorageStats getStorageStats() const;
private:
Id addNodeHierarchy(Node::NodeType nodeType, NameHierarchy nameHierarchy, bool defined);
Id addNodeHierarchy(Node::NodeType type, const ParseFunction& function, bool defined);
@@ -205,6 +208,8 @@ private:
void log(std::string type, std::string str, const ParseLocation& location) const;
SearchIndex m_tokenIndex;
SearchIndex m_commandIndex;
SqliteStorage m_sqliteStorage;
mutable std::map <FilePath, Id> m_fileNodeIds;
+32
View File
@@ -0,0 +1,32 @@
#ifndef STORAGE_STATS_H
#define STORAGE_STATS_H
struct StorageStats
{
StorageStats()
: nodeCount(0)
, edgeCount(0)
, charCount(0)
, wordCount(0)
, searchNodeCount(0)
, fileCount(0)
, fileLOCCount(0)
, sourceLocationCount(0)
, errorCount(0)
{}
size_t nodeCount;
size_t edgeCount;
size_t charCount;
size_t wordCount;
size_t searchNodeCount;
size_t fileCount;
size_t fileLOCCount;
size_t sourceLocationCount;
size_t errorCount;
};
#endif // STORAGE_STATS_H
+4
View File
@@ -10,6 +10,7 @@
#include "data/graph/Node.h"
#include "data/search/SearchMatch.h"
#include "data/StorageStats.h"
struct FileInfo;
class Graph;
@@ -37,6 +38,7 @@ public:
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::string& query) const = 0;
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const = 0;
virtual std::shared_ptr<Graph> getGraphForAll() const = 0;
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const = 0;
virtual std::vector<Id> getActiveTokenIdsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
@@ -60,6 +62,8 @@ public:
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const = 0;
virtual TimePoint getFileModificationTime(const FilePath& filePath) const = 0;
virtual StorageStats getStorageStats() const = 0;
};
#endif // STORAGE_ACCESS_H
@@ -113,6 +113,16 @@ std::vector<SearchMatch> StorageAccessProxy::getSearchMatchesForTokenIds(const s
return std::vector<SearchMatch>();
}
std::shared_ptr<Graph> StorageAccessProxy::getGraphForAll() const
{
if (hasSubject())
{
return m_subject->getGraphForAll();
}
return std::make_shared<Graph>();
}
std::shared_ptr<Graph> StorageAccessProxy::getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const
{
if (hasSubject())
@@ -274,3 +284,13 @@ TimePoint StorageAccessProxy::getFileModificationTime(const FilePath& filePath)
return TimePoint(boost::posix_time::not_a_date_time);
}
StorageStats StorageAccessProxy::getStorageStats() const
{
if (hasSubject())
{
return m_subject->getStorageStats();
}
return StorageStats();
}
+3
View File
@@ -26,6 +26,7 @@ public:
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::string& query) const;
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const;
virtual std::shared_ptr<Graph> getGraphForAll() const;
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds) const;
virtual std::vector<Id> getActiveTokenIdsForTokenIds(const std::vector<Id>& tokenIds) const;
@@ -51,6 +52,8 @@ public:
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const;
virtual TimePoint getFileModificationTime(const FilePath& filePath) const;
virtual StorageStats getStorageStats() const;
private:
StorageAccess* m_subject;
};
+22
View File
@@ -45,6 +45,28 @@ std::string SearchMatch::searchMatchesToString(const std::vector<SearchMatch>& m
return ss.str();
}
SearchMatch SearchMatch::createCommand(CommandType type)
{
SearchMatch match;
match.nameHierarchy = NameHierarchy(getCommandName(type));
match.typeName = "command";
match.searchType = SEARCH_COMMAND;
return match;
}
std::string SearchMatch::getCommandName(CommandType type)
{
switch (type)
{
case COMMAND_ALL:
return "overview";
case COMMAND_ERROR:
return "error";
}
return "none";
}
SearchMatch::SearchMatch()
: typeName("")
, searchType(SEARCH_NONE)
+9
View File
@@ -19,11 +19,20 @@ struct SearchMatch
SEARCH_OPERATOR
};
enum CommandType
{
COMMAND_ALL,
COMMAND_ERROR
};
static void log(const std::vector<SearchMatch>& matches, const std::string& query);
static std::string getSearchTypeName(SearchType type);
static std::string searchMatchesToString(const std::vector<SearchMatch>& matches);
static SearchMatch createCommand(CommandType type);
static std::string getCommandName(CommandType type);
SearchMatch();
SearchMatch(const std::string& query);
+5
View File
@@ -122,3 +122,8 @@ bool ProjectSettings::setSourceExtensions(const std::vector<std::string> &source
{
return setValues("source/extensions/source_extensions", sourceExtensions);
}
std::string ProjectSettings::getDescription() const
{
return getValue<std::string>("info/description", "");
}
+3
View File
@@ -18,6 +18,9 @@ public:
virtual void save(const FilePath& filePath);
// info
std::string getDescription() const;
// language settings
std::string getLanguage() const;
bool setLanguage(const std::string& language);
@@ -0,0 +1,20 @@
#ifndef MESSAGE_ACTIVATE_ALL_H
#define MESSAGE_ACTIVATE_ALL_H
#include "utility/messaging/Message.h"
class MessageActivateAll
: public Message<MessageActivateAll>
{
public:
MessageActivateAll()
{
}
static const std::string getStaticType()
{
return "MessageActivateAll";
}
};
#endif // MESSAGE_ACTIVATE_ALL_H
@@ -0,0 +1,32 @@
#ifndef MESSAGE_ACTIVATE_TOKEN_IDS_H
#define MESSAGE_ACTIVATE_TOKEN_IDS_H
#include "utility/messaging/Message.h"
#include "utility/types.h"
class MessageActivateTokenIds
: public Message<MessageActivateTokenIds>
{
public:
MessageActivateTokenIds(const std::vector<Id>& tokenIds)
: tokenIds(tokenIds)
{
}
static const std::string getStaticType()
{
return "MessageActivateTokenIds";
}
virtual void print(std::ostream& os) const
{
for (const Id& id : tokenIds)
{
os << id << " ";
}
}
const std::vector<Id> tokenIds;
};
#endif // MESSAGE_ACTIVATE_TOKEN_IDS_H
+7
View File
@@ -128,6 +128,13 @@ namespace utility
return res.first == prefix.end();
}
std::string toUpperCase(const std::string& in)
{
std::string out;
std::transform(in.begin(), in.end(), std::back_inserter(out), toupper);
return out;
}
std::string toLowerCase(const std::string& in)
{
std::string out;
+1
View File
@@ -34,6 +34,7 @@ namespace utility
bool isPrefix(const std::string& prefix, const std::string& text);
std::string toUpperCase(const std::string& in);
std::string toLowerCase(const std::string& in);
bool equalsCaseInsensitive(const std::string& a, const std::string& b);
@@ -105,7 +105,7 @@ void QtAutocompletionDelegate::paint(QPainter* painter, const QStyleOptionViewIt
QColor color("#FFFFFF");
Node::NodeType nodeType = static_cast<Node::NodeType>(index.sibling(index.row(), index.column() + 3).data().toInt());
if (type.size())
if (type.size() && type != "command")
{
color = QColor(GraphViewStyle::getNodeColor(Node::getTypeString(nodeType), false).fill.c_str());
}
+25 -19
View File
@@ -10,6 +10,7 @@
#include <qscrollbar.h>
#include "utility/messaging/type/MessageActivateTokenLocations.h"
#include "utility/messaging/type/MessageActivateTokenIds.h"
#include "utility/messaging/type/MessageShowFile.h"
#include "utility/messaging/type/MessageFocusIn.h"
#include "utility/messaging/type/MessageFocusOut.h"
@@ -369,21 +370,41 @@ void QtCodeArea::mouseReleaseEvent(QMouseEvent* event)
m_eventPosition = event->pos();
setIDECursorPosition();
}
else
else if (!m_fileWidget->getErrorMessages().size())
{
QTextCursor cursor = this->cursorForPosition(event->pos());
std::vector<Id> locationIds = findLocationIdsForPosition(cursor.position());
if (locationIds.size() && !m_fileWidget->getErrorMessages().size())
std::vector<const Annotation*> annotations = getAnnotationsForPosition(cursor.position());
std::vector<Id> locationIds;
std::vector<Id> tokenIds;
for (const Annotation* annotation : annotations)
{
if (annotation->locationId > 0)
{
locationIds.push_back(annotation->locationId);
}
if (annotation->tokenId > 0)
{
tokenIds.push_back(annotation->tokenId);
}
}
if (locationIds.size())
{
MessageActivateTokenLocations(locationIds).dispatch();
}
else if (tokenIds.size())
{
MessageActivateTokenIds(tokenIds).dispatch();
}
}
}
}
void QtCodeArea::mouseDoubleClickEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton)
if (event->button() == Qt::LeftButton && m_fileWidget->getFilePath().str().size())
{
MessageShowFile(m_fileWidget->getFilePath().str(), (m_fileWidget->getErrorMessages().size() > 0)).dispatch();
}
@@ -482,21 +503,6 @@ void QtCodeArea::setIDECursorPosition()
MessageMoveIDECursor(m_locationFile->getFilePath().str(), lineColumn.first, lineColumn.second).dispatch();
}
std::vector<Id> QtCodeArea::findLocationIdsForPosition(int pos) const
{
std::vector<Id> locationIds;
for (const Annotation& annotation : m_annotations)
{
if (!annotation.isScope && pos >= annotation.start && pos <= annotation.end)
{
locationIds.push_back(annotation.locationId);
}
}
return locationIds;
}
std::vector<const QtCodeArea::Annotation*> QtCodeArea::getAnnotationsForPosition(int pos) const
{
std::vector<const QtCodeArea::Annotation*> annotations;
-1
View File
@@ -134,7 +134,6 @@ private:
std::string fill;
};
std::vector<Id> findLocationIdsForPosition(int pos) const;
std::vector<const Annotation*> getAnnotationsForPosition(int pos) const;
void createAnnotations(std::shared_ptr<TokenLocationFile> locationFile);
+5
View File
@@ -57,6 +57,11 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent)
titleLayout->addWidget(m_title);
if (m_title->text().size() == 0)
{
m_title->hide();
}
m_titleBar->setMinimumHeight(m_title->height() + 4);
m_referenceCount = new QLabel(this);
+1 -1
View File
@@ -324,7 +324,7 @@ std::shared_ptr<QtGraphNode> QtGraphView::createNodeRecursive(
std::shared_ptr<QtGraphNode> newNode;
if (node.isGraphNode())
{
newNode = std::make_shared<QtGraphNodeData>(node.data, node.hasParent, node.childVisible);
newNode = std::make_shared<QtGraphNodeData>(node.data, node.name, node.hasParent, node.childVisible);
}
else if (node.isAccessNode())
{
@@ -7,20 +7,13 @@
#include "data/graph/token_component/TokenComponentSignature.h"
QtGraphNodeData::QtGraphNodeData(const Node* data, bool hasParent, bool childVisible)
QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible)
: m_data(data)
, m_childVisible(childVisible)
{
this->setAcceptHoverEvents(true);
if (!hasParent)
{
this->setName(data->getFullName());
}
else
{
this->setName(data->getName());
}
this->setName(name);
std::string toolTip = data->getTypeString();
if (!data->isDefined() && !data->isType(Node::NODE_UNDEFINED))
@@ -7,7 +7,7 @@ class QtGraphNodeData
: public QtGraphNode
{
public:
QtGraphNodeData(const Node* data, bool hasParent, bool childVisible);
QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible);
virtual ~QtGraphNodeData();
const Node* getData() const;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 321 KiB

+122 -107
View File
@@ -24,13 +24,13 @@
body {
padding-top: 20px;
}
#nav {
position:fixed;
width: 20%;
margin-left: 2%;
}
.tocify {
position:static;
width: 100%;
@@ -50,14 +50,14 @@
<div class="container-fluid">
<div class="row-fluid">
<div class="col-xs-12 col-sm-3">
<div id="nav">
<div class="col-xs-12 col-sm-3">
<div id="nav">
<div class="row">
<div class="col-xs-12">
<p><span class="glyphicon glyphicon-arrow-left"></span> <a href="http://www.coati.io/">back to coati.io</a></p>
</div>
</div>
<div class="row" style="height:20px;"></div>
<div class="row" style="height:10px;"></div>
<div class="row">
<div class="col-xs-12">
<div id="toc"></div><!-- Our table of contents will be here !-->
@@ -75,7 +75,7 @@
<div class="row" style="text-align:center;">
<p>Documentation for version 0.5</p>
</div>
<div class="row" style="height:120px;"></div>
<address>
<strong>Coati Software OG.</strong><br>
@@ -83,13 +83,13 @@
5412 Puch bei Hallein<br>
Austria<br>
</address>
<address>
<strong>Contact</strong><br>
<a href="http://coati.io">coati.io</a><br>
<a href="mailto:mail@coati.io" target="_top">mail@coati.io</a><br>
</address>
<div class="row" style="height:40px;"></div>
<h1>QUICK START GUIDE</h1>
@@ -198,7 +198,7 @@
<li>or Press ESC to stop the analysis (Coati will provide all information gathered so far and the analysis can be continued later by <a href="#Refresh">refreshing</a>).</li>
</ul>
</div>
<p>After analysis has finished, Coati will look for a function named <code>main</code> and activate it. In case it's not there, the first analyzed file will be activated. If the analysis found errors in your code, the code view will display them. You can see the error message by hovering an error's location.</p>
<p>After analysis has finished, Coati will show an overview of all analysed symbols in the <a href="#GraphView">graph view</a> and some statistics in the <a href="#CodeView">code view</a>. If the analysis found errors in your code, the code view will display them. You can see the error message by hovering an error's location.</p>
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<img src="img/error_view.png" style="width:100%;">
@@ -416,98 +416,6 @@
<h1>USER INTERFACE</h1>
<h2>Start Window</h2>
<p>On every start of Coati you are shown the start window. It allows for creating new projects or opening existing ones.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/start_screen.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Clicking <var>New Project</var> will lead you to <a href="#ProjectSetupWindow">Project Setup</a>.</li>
<li>Clicking <var>Open Project</var> will let you open an existing Coati project by choosing from a file dialog.</li>
<li>Clicking on one of the <var>Recent Projects</var> will open this project. The list shows a maximum of 7 items ordered by recent first.</li>
<li>Pressing <var>ESC</var> will close the window.</li>
</ul>
<h2>Path List Box</h2>
<p>The Path List Box is a user interface element that is used within the <a href="#PreferencesWindow">Preferences Window</a> and the <a href="#ProjectSetupWindow">Project Setup Window</a>. It allows for entering a list of file and directory paths.</p>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<img src="img/path_list_box.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Click the "+" icon to add a new path line.</li>
<li>Click the "-" icon to remove a selected path line.</li>
<li>Click a path line to select it.</li>
<li>Enter the path by typing on your keyboard</li>
<li>Click "..." within the path line to open a file dialog for choosing a file or directory path.</li>
<li>Directly add multiple paths into the box by dropping elements from your filesystem.</li>
</ul>
<h2>Preferences Window</h2>
<p>The Preferences window lets you define settings for all projects. You can open the Preferences from the menu via <a href="#Help">Help/Preferences</a> or from the <a href="#ProjectSetupWindow">Project Setup Window</a> by pressing the <var>Preferences</var> button.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/preferences_screen.png" style="width:100%;">
</div>
</div>
<table class="table table-hover">
<thead>
<tr> <th>Setting</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row">Header Search Paths</th> <td>Set header search paths that are used for <strong>all</strong> of your projects (e.g. std headers). (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>. For instructions on how to find the system header paths see <a href="#FindingSystemHeaderLocations">Finding System Header Locations</a>)</td> </tr>
<tr> <th scope="row">Framework Search Paths</th> <td>Mac only. Define the search paths for <code>.framework</code> files for all of your projects. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
</tbody>
</table>
<h2>Project Setup Window</h2>
<p>The Project Setup Window lets you create a new Coati project.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/project_setup_screen.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Clicking <var>Cancel</var> will close the window.</li>
<li>Clicking <var>Create</var> will check your inputs, save the new project file and start analyzing the source files.</li>
<li>Pressing <var>ESC</var> will close the window.</li>
</ul>
<table class="table table-hover">
<thead>
<tr> <th>Setting</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row">Name</th> <td>The name of the project. This will also be the name of the project file.</td> </tr>
<tr> <th scope="row">Location</th> <td>Choose the location of the project file from the dialog.</td> </tr>
<tr> <th scope="row">Language</th> <td>Select the language of your project. (See <a href="#SupportedLanguages">Language Support</a>)</td> </tr>
<tr> <th scope="row">Standard</th> <td>Select the language standard that should be used for analyzing your project. (See <a href="#SupportedLanguages">Language Support</a>)</td> </tr>
<tr> <th scope="row">Analyzed Paths</th> <td>Specify one or multiple locations that contain all the source and header files that should be analyzed by Coati. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
<tr> <th scope="row">Header Search Paths</th> <td>Specify where Coati should be looking for included headers. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
<tr> <th scope="row">Framework Search Paths</th> <td>Mac only. Define the search paths for <code>.framework</code> files for your project. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
</tbody>
</table>
<h2>Enter License Window</h2>
<p>The Enter License Window appears on your first start of Coati and is used to enter and check your Coati license key.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/enter_license_screen.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Copy and Paste your license key from your "Coati 0 License Key" e-mail into the textfield. The key should be formated as shown by the placeholder text.</li>
<li>Clicking <var>Activate</var> will check if your license key is valid and close the window. Otherwise an error message will be displayed.</li>
</ul>
<h2>Main Window</h2>
<h3>Widget Windows</h3>
@@ -539,10 +447,105 @@
</ul>
</p>
<h2>Other Windows</h2>
<h3>Start Window</h3>
<p>On every start of Coati you are shown the start window. It allows for creating new projects or opening existing ones.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/start_screen.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Clicking <var>New Project</var> will lead you to <a href="#ProjectSetupWindow">Project Setup</a>.</li>
<li>Clicking <var>Open Project</var> will let you open an existing Coati project by choosing from a file dialog.</li>
<li>Clicking on one of the <var>Recent Projects</var> will open this project. The list shows a maximum of 7 items ordered by recent first.</li>
<li>Pressing <var>ESC</var> will close the window.</li>
</ul>
<h2>Menu Structure</h2>
<h3>Path List Box</h3>
<p>The Path List Box is a user interface element that is used within the <a href="#PreferencesWindow">Preferences Window</a> and the <a href="#ProjectSetupWindow">Project Setup Window</a>. It allows for entering a list of file and directory paths.</p>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<img src="img/path_list_box.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Click the "+" icon to add a new path line.</li>
<li>Click the "-" icon to remove a selected path line.</li>
<li>Click a path line to select it.</li>
<li>Enter the path by typing on your keyboard</li>
<li>Click "..." within the path line to open a file dialog for choosing a file or directory path.</li>
<li>Directly add multiple paths into the box by dropping elements from your filesystem.</li>
</ul>
<h3>Project</h3>
<h3>Preferences Window</h3>
<p>The Preferences window lets you define settings for all projects. You can open the Preferences from the menu via <a href="#Help">Help/Preferences</a> or from the <a href="#ProjectSetupWindow">Project Setup Window</a> by pressing the <var>Preferences</var> button.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/preferences_screen.png" style="width:100%;">
</div>
</div>
<table class="table table-hover">
<thead>
<tr> <th>Setting</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row">Header Search Paths</th> <td>Set header search paths that are used for <strong>all</strong> of your projects (e.g. std headers). (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>. For instructions on how to find the system header paths see <a href="#FindingSystemHeaderLocations">Finding System Header Locations</a>)</td> </tr>
<tr> <th scope="row">Framework Search Paths</th> <td>Mac only. Define the search paths for <code>.framework</code> files for all of your projects. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
</tbody>
</table>
<h3>Project Setup Window</h3>
<p>The Project Setup Window lets you create a new Coati project.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/project_setup_screen.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Clicking <var>Cancel</var> will close the window.</li>
<li>Clicking <var>Create</var> will check your inputs, save the new project file and start analyzing the source files.</li>
<li>Pressing <var>ESC</var> will close the window.</li>
</ul>
<table class="table table-hover">
<thead>
<tr> <th>Setting</th> <th>Description</th> </tr>
</thead>
<tbody>
<tr> <th scope="row">Name</th> <td>The name of the project. This will also be the name of the project file.</td> </tr>
<tr> <th scope="row">Location</th> <td>Choose the location of the project file from the dialog.</td> </tr>
<tr> <th scope="row">Language</th> <td>Select the language of your project. (See <a href="#SupportedLanguages">Language Support</a>)</td> </tr>
<tr> <th scope="row">Standard</th> <td>Select the language standard that should be used for analyzing your project. (See <a href="#SupportedLanguages">Language Support</a>)</td> </tr>
<tr> <th scope="row">Analyzed Paths</th> <td>Specify one or multiple locations that contain all the source and header files that should be analyzed by Coati. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
<tr> <th scope="row">Header Search Paths</th> <td>Specify where Coati should be looking for included headers. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
<tr> <th scope="row">Framework Search Paths</th> <td>Mac only. Define the search paths for <code>.framework</code> files for your project. (For instructions on how to add paths see <a href="#PathListBox">Path List Box</a>.)</td> </tr>
</tbody>
</table>
<h3>Enter License Window</h3>
<p>The Enter License Window appears on your first start of Coati and is used to enter and check your Coati license key.</p>
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<img src="img/enter_license_screen.png" style="width:100%;">
</div>
</div>
<strong>Interactions:</strong>
<ul>
<li>Copy and Paste your license key from your "Coati 0 License Key" e-mail into the textfield. The key should be formated as shown by the placeholder text.</li>
<li>Clicking <var>Activate</var> will check if your license key is valid and close the window. Otherwise an error message will be displayed.</li>
</ul>
<h2>Menu</h2>
<h3>Structure</h3>
<h4>Project</h4>
<ul>
<li>
<strong>New Project</strong>
@@ -592,7 +595,7 @@
</li>
</ul>
<h3>Edit</h3>
<h4>Edit</h4>
<ul>
<li>
<strong>Back</strong>
@@ -631,7 +634,7 @@
</li>
</ul>
<h3>View</h3>
<h4>View</h4>
<ul>
<li>
<strong>Show Title Bars</strong>
@@ -686,7 +689,7 @@
</li>
</ul>
<h3>Help</h3>
<h4>Help</h4>
<ul>
<li>
<strong>About</strong>
@@ -716,7 +719,7 @@
</ul>
<h2>Shortcuts</h2>
<h3>Shortcuts</h3>
<table class="table table-hover">
<thead>
<tr> <th>Shortcut</th> <th>Windows</th> <th>Mac OS X</th> <th>Linux</th> </tr>
@@ -1004,6 +1007,18 @@
<li>Pressing enter will select the search result and send the search request.</li>
</ul>
<h3>Keywords</h3>
<p>Additionally the search view provides specific keywords that select a certein group of symbols.</p>
<table class="table table-hover">
<thead>
<tr> <th>keyword</th> <th>effect</th> </tr>
</thead>
<tbody>
<tr> <th scope="row">overview</th> <td>Shows an overview of all analysed symbols in the <a href="#GraphView">graph view</a> and some statistics in the <a href="#CodeView">code view</a>.</td> </tr>
<tr> <th scope="row">error</th> <td>Shows all errors in the <a href="#CodeView">code view</a>.</td> </tr>
</tbody>
</table>
<div class="row" style="height:80px;"></div>