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:
@@ -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](); // <- 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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);"
|
||||
);
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
int getNodeCount() const;
|
||||
int getEdgeCount() const;
|
||||
int getFileCount() const;
|
||||
int getFileLOCCount() const;
|
||||
int getSourceLocationCount() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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", "");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user