ui: Added show definition context menu action for graph nodes (issue #83)

* use 'show definition' context menu action or 'Ctrl/Cmd + Left Click' to show definition of node in code
This commit is contained in:
Eberhard Graether
2018-07-22 14:30:56 +02:00
parent 0b5ad33a8c
commit ad6f5c8727
16 changed files with 267 additions and 53 deletions
+2
View File
@@ -418,6 +418,8 @@ add_files(
utility/messaging/filter_types/MessageFilterFocusInOut.h
utility/messaging/filter_types/MessageFilterSearchAutocomplete.h
utility/messaging/type/code/MessageCodeShowDefinition.h
utility/messaging/type/error/MessageActivateErrors.h
utility/messaging/type/error/MessageErrorCountClear.h
utility/messaging/type/error/MessageErrorCountUpdate.h
+95 -16
View File
@@ -287,6 +287,91 @@ void CodeController::handleMessage(MessageChangeFileView* message)
}
}
void CodeController::handleMessage(MessageCodeShowDefinition* message)
{
TRACE("code show definition");
Id nodeId = message->nodeId;
std::shared_ptr<SourceLocationCollection> collection = m_storageAccess->getSourceLocationsForTokenIds({ nodeId });
if (!collection->getSourceLocationFileCount())
{
LOG_ERROR("MessageCodeShowDefinition did not contain a nodeId with location files.");
return;
}
size_t lineNumber = 1;
FilePath filePath;
// use first scope location for nodeId, otherwise first location
if (collection->getSourceLocationCount())
{
std::shared_ptr<SourceLocationCollection> filteredCollection = std::make_shared<SourceLocationCollection>();
bool addedLocation = false;
collection->forEachSourceLocation(
[&](SourceLocation* location)
{
if (addedLocation || !location->isStartLocation())
{
return;
}
if (location->isScopeLocation())
{
filteredCollection->addSourceLocationCopy(location);
filteredCollection->addSourceLocationCopy(location->getEndLocation());
filePath = location->getFilePath();
lineNumber = location->getLineNumber();
addedLocation = true;
return;
}
}
);
if (!addedLocation)
{
SourceLocation* location = collection->getSourceLocationFiles().begin()->second->getSourceLocations().begin()->get();
filteredCollection->addSourceLocationCopy(location);
filteredCollection->addSourceLocationCopy(location->getOtherLocation());
filePath = location->getFilePath();
lineNumber = location->getStartLocation()->getLineNumber();
}
collection = filteredCollection;
}
else // otherwise first file
{
filePath = collection->getSourceLocationFiles().begin()->second->getFilePath();
}
std::vector<CodeSnippetParams> snippets = getSnippetsForFile(collection->getSourceLocationFiles().begin()->second);
if (snippets.size() != 1)
{
LOG_ERROR("MessageCodeShowDefinition snippet count is not 1");
return;
}
snippets[0].insertSnippet = true;
m_collection->addSourceLocationCopies(collection.get());
saveOrRestoreViewMode(message);
CodeView* view = getView();
CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_LINE);
scrollParams.filePath = filePath;
scrollParams.line = lineNumber;
view->scrollTo(scrollParams);
CodeView::CodeParams params;
params.showContents = !message->isReplayed();
addAllSourceLocations(&snippets);
getView()->showCodeSnippets(snippets, params);
}
void CodeController::handleMessage(MessageDeactivateEdge* message)
{
if (message->scrollToDefinition)
@@ -394,7 +479,7 @@ void CodeController::clear()
{
getView()->clear();
m_collection.reset();
m_collection = std::make_shared<SourceLocationCollection>();
}
std::vector<CodeSnippetParams> CodeController::getSnippetsForFileWithState(
@@ -402,20 +487,18 @@ std::vector<CodeSnippetParams> CodeController::getSnippetsForFileWithState(
{
TRACE();
std::shared_ptr<SourceLocationFile> file = m_collection->getSourceLocationFileByPath(filePath);
if (!file)
{
return {};
}
std::vector<CodeSnippetParams> snippets;
switch (state)
{
case CodeView::FILE_SNIPPETS:
{
std::shared_ptr<SourceLocationFile> file = m_collection->getSourceLocationFileByPath(filePath);
if (!file)
{
return snippets;
}
snippets = getSnippetsForFile(file);
}
snippets = getSnippetsForFile(file);
break;
case CodeView::FILE_MAXIMIZED:
@@ -431,12 +514,8 @@ std::vector<CodeSnippetParams> CodeController::getSnippetsForFileWithState(
// make a copy of SourceLocationFile so that isWhole flag is different for first snippet adding the file
// and second snippet adding the content
params.locationFile =
std::make_shared<SourceLocationFile>(*m_collection->getSourceLocationFileByPath(filePath).get());
if (params.locationFile)
{
params.locationFile->setIsWhole(true);
}
params.locationFile = std::make_shared<SourceLocationFile>(*file.get());
params.locationFile->setIsWhole(true);
snippets.push_back(params);
}
@@ -6,6 +6,7 @@
#include "utility/file/FilePath.h"
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/code/MessageCodeShowDefinition.h"
#include "utility/messaging/type/error/MessageActivateErrors.h"
#include "utility/messaging/type/error/MessageErrorCountClear.h"
#include "utility/messaging/type/error/MessageShowError.h"
@@ -42,6 +43,7 @@ class CodeController
, public MessageListener<MessageActivateTokens>
, public MessageListener<MessageActivateTrailEdge>
, public MessageListener<MessageChangeFileView>
, public MessageListener<MessageCodeShowDefinition>
, public MessageListener<MessageDeactivateEdge>
, public MessageListener<MessageErrorCountClear>
, public MessageListener<MessageFlushUpdates>
@@ -66,6 +68,7 @@ private:
virtual void handleMessage(MessageActivateTokens* message);
virtual void handleMessage(MessageActivateTrailEdge* message);
virtual void handleMessage(MessageChangeFileView* message);
virtual void handleMessage(MessageCodeShowDefinition* message);
virtual void handleMessage(MessageDeactivateEdge* message);
virtual void handleMessage(MessageErrorCountClear* message);
virtual void handleMessage(MessageFlushUpdates* message);
@@ -139,6 +139,18 @@ void UndoRedoController::handleMessage(MessageChangeFileView* message)
processCommand(command);
}
void UndoRedoController::handleMessage(MessageCodeShowDefinition* message)
{
if (sameMessageTypeAsLast(message) &&
static_cast<MessageCodeShowDefinition*>(lastMessage())->nodeId == message->nodeId)
{
return;
}
Command command(std::make_shared<MessageCodeShowDefinition>(*message), Command::ORDER_ADAPT);
processCommand(command);
}
void UndoRedoController::handleMessage(MessageDeactivateEdge* message)
{
if (m_iterator == m_list.begin())
@@ -5,6 +5,7 @@
#include "utility/messaging/MessageBase.h"
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/code/MessageCodeShowDefinition.h"
#include "utility/messaging/type/error/MessageActivateErrors.h"
#include "utility/messaging/type/error/MessageShowError.h"
#include "utility/messaging/type/history/MessageHistoryRedo.h"
@@ -44,6 +45,7 @@ class UndoRedoController
, public MessageListener<MessageActivateTrail>
, public MessageListener<MessageActivateTrailEdge>
, public MessageListener<MessageChangeFileView>
, public MessageListener<MessageCodeShowDefinition>
, public MessageListener<MessageDeactivateEdge>
, public MessageListener<MessageGraphNodeBundleSplit>
, public MessageListener<MessageGraphNodeExpand>
@@ -93,6 +95,7 @@ private:
virtual void handleMessage(MessageActivateTrail* message);
virtual void handleMessage(MessageActivateTrailEdge* message);
virtual void handleMessage(MessageChangeFileView* message);
virtual void handleMessage(MessageCodeShowDefinition* message);
virtual void handleMessage(MessageDeactivateEdge* message);
virtual void handleMessage(MessageGraphNodeBundleSplit* message);
virtual void handleMessage(MessageGraphNodeExpand* message);
@@ -78,9 +78,30 @@ SourceLocation* SourceLocationCollection::addSourceLocation(
return file->addSourceLocation(type, locationId, tokenIds, startLineNumber, startColumnNumber, endLineNumber, endColumnNumber);
}
SourceLocation* SourceLocationCollection::addSourceLocationCopy(SourceLocation* location)
SourceLocation* SourceLocationCollection::addSourceLocationCopy(const SourceLocation* location)
{
return createSourceLocationFile(location->getFilePath())->addSourceLocationCopy(location);
SourceLocationFile* other = location->getSourceLocationFile();
SourceLocationFile* file =
createSourceLocationFile(location->getFilePath(), other->isWhole(), other->isComplete(), other->isIndexed());
return file->addSourceLocationCopy(location);
}
void SourceLocationCollection::addSourceLocationCopies(const SourceLocationCollection* other)
{
other->forEachSourceLocationFile(
[this](std::shared_ptr<SourceLocationFile> otherFile)
{
SourceLocationFile* file = createSourceLocationFile(
otherFile->getFilePath(), otherFile->isWhole(), otherFile->isComplete(), otherFile->isIndexed());
otherFile->forEachSourceLocation(
[file](SourceLocation* otherLocation)
{
file->addSourceLocationCopy(otherLocation);
}
);
}
);
}
void SourceLocationCollection::addSourceLocationFile(std::shared_ptr<SourceLocationFile> file)
@@ -105,7 +126,8 @@ void SourceLocationCollection::forEachSourceLocation(std::function<void(SourceLo
}
}
SourceLocationFile* SourceLocationCollection::createSourceLocationFile(const FilePath& filePath)
SourceLocationFile* SourceLocationCollection::createSourceLocationFile(
const FilePath& filePath, bool isWhole, bool isComplete, bool isIndexed)
{
SourceLocationFile* file = getSourceLocationFileByPath(filePath).get();
if (file)
@@ -113,7 +135,8 @@ SourceLocationFile* SourceLocationCollection::createSourceLocationFile(const Fil
return file;
}
std::shared_ptr<SourceLocationFile> filePtr = std::make_shared<SourceLocationFile>(filePath, false, false, false);
std::shared_ptr<SourceLocationFile> filePtr =
std::make_shared<SourceLocationFile>(filePath, isWhole, isComplete, isIndexed);
m_files.emplace(filePath, filePtr);
return filePtr.get();
}
@@ -32,7 +32,9 @@ public:
LocationType type, Id locationId, std::vector<Id> tokenIds, const FilePath& filePath,
size_t startLineNumber, size_t startColumnNumber,
size_t endLineNumber, size_t endColumnNumber);
SourceLocation* addSourceLocationCopy(SourceLocation* location);
SourceLocation* addSourceLocationCopy(const SourceLocation* location);
void addSourceLocationCopies(const SourceLocationCollection* other);
void addSourceLocationFile(std::shared_ptr<SourceLocationFile> file);
@@ -40,7 +42,8 @@ public:
void forEachSourceLocation(std::function<void(SourceLocation*)> func) const;
private:
SourceLocationFile* createSourceLocationFile(const FilePath& filePath);
SourceLocationFile* createSourceLocationFile(
const FilePath& filePath, bool isWhole = false, bool isComplete = false, bool isIndexed = false);
std::map<FilePath, std::shared_ptr<SourceLocationFile>> m_files;
};
@@ -215,6 +215,21 @@ std::wostream& operator<<(std::wostream& ostream, const SourceLocationFile& file
{
ostream << L"file \"" << file.getFilePath().wstr() << L"\"";
if (file.isWhole())
{
ostream << L" whole";
}
if (file.isComplete())
{
ostream << L" complete";
}
if (file.isIndexed())
{
ostream << L" indexed";
}
size_t line = 0;
file.forEachSourceLocation(
[&ostream, &line](SourceLocation* location)
+3 -1
View File
@@ -1380,6 +1380,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
if (nonFileIds.size())
{
// FIXME: can we use get SqliteIndexStorage::getSourceLocationsForElementIds() here instead?
std::vector<Id> locationIds;
std::unordered_map<Id, Id> locationIdToElementIdMap;
for (const StorageOccurrence& occurrence: m_sqliteIndexStorage.getOccurrencesForElementIds(nonFileIds))
@@ -1403,6 +1404,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
}
FilePath path = getFileNodePath(sourceLocation.fileNodeId);
// FIXME: This shouldn't be necessary since all files are stored, even non-indexed
if (path.empty())
{
const StorageNode fileNode = m_sqliteIndexStorage.getNodeById(sourceLocation.fileNodeId);
@@ -1421,7 +1423,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
collection->addSourceLocation(
type,
sourceLocation.id,
std::vector<Id>(1, it->second),
{ it->second },
path,
sourceLocation.startLine,
sourceLocation.startCol,
@@ -0,0 +1,29 @@
#ifndef MESSAGE_CODE_SHOW_DEFINITION_H
#define MESSAGE_CODE_SHOW_DEFINITION_H
#include "utility/messaging/Message.h"
#include "utility/types.h"
class MessageCodeShowDefinition
: public Message<MessageCodeShowDefinition>
{
public:
static const std::string getStaticType()
{
return "MessageCodeShowDefinition";
}
MessageCodeShowDefinition(Id nodeId)
: nodeId(nodeId)
{
}
virtual void print(std::wostream& os) const
{
os << nodeId;
}
const Id nodeId;
};
#endif // MESSAGE_CODE_SHOW_DEFINITION_H