ui/logic/data: show parse errors in CodeView
This change saves the errors while parsing in the Storage and displays them in the CodeView. The error messages can be read in the tooltip on hovering. The error count is visible in the status bar.
This commit is contained in:
@@ -47,8 +47,6 @@ void Application::loadProject(const std::string& projectSettingsFilePath)
|
||||
|
||||
m_project->loadProjectSettings(projectSettingsFilePath);
|
||||
m_project->parseCode();
|
||||
|
||||
activateInitialNode();
|
||||
}
|
||||
|
||||
void Application::loadSource(const std::string& sourceDirectoryPath)
|
||||
@@ -58,16 +56,12 @@ void Application::loadSource(const std::string& sourceDirectoryPath)
|
||||
m_project->clearProjectSettings();
|
||||
m_project->setSourceDirectoryPath(sourceDirectoryPath);
|
||||
m_project->parseCode();
|
||||
|
||||
activateInitialNode();
|
||||
}
|
||||
|
||||
void Application::reloadProject()
|
||||
{
|
||||
m_project->clearStorage();
|
||||
m_project->parseCode();
|
||||
|
||||
activateInitialNode();
|
||||
}
|
||||
|
||||
void Application::saveProject(const std::string& projectSettingsFilePath)
|
||||
@@ -78,8 +72,13 @@ void Application::saveProject(const std::string& projectSettingsFilePath)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::activateInitialNode() const
|
||||
void Application::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
if (message->errorCount > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Id mainId = m_graphAccessProxy->getIdForNodeWithName("main");
|
||||
|
||||
if (!mainId)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "component/ComponentManager.h"
|
||||
#include "Project.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/messaging/type/MessageLoadProject.h"
|
||||
#include "utility/messaging/type/MessageLoadSource.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
@@ -17,7 +18,8 @@ class GraphAccessProxy;
|
||||
class LocationAccessProxy;
|
||||
|
||||
class Application
|
||||
: public MessageListener<MessageLoadProject>
|
||||
: public MessageListener<MessageFinishedParsing>
|
||||
, public MessageListener<MessageLoadProject>
|
||||
, public MessageListener<MessageLoadSource>
|
||||
, public MessageListener<MessageRefresh>
|
||||
, public MessageListener<MessageSaveProject>
|
||||
@@ -35,8 +37,7 @@ public:
|
||||
private:
|
||||
Application();
|
||||
|
||||
void activateInitialNode() const;
|
||||
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
virtual void handleMessage(MessageLoadProject* message);
|
||||
virtual void handleMessage(MessageLoadSource* message);
|
||||
virtual void handleMessage(MessageRefresh* message);
|
||||
|
||||
@@ -13,6 +13,8 @@ add_files(
|
||||
data/parser/cxx/ASTConsumer.h
|
||||
data/parser/cxx/ASTVisitor.cpp
|
||||
data/parser/cxx/ASTVisitor.h
|
||||
data/parser/cxx/CxxDiagnosticConsumer.cpp
|
||||
data/parser/cxx/CxxDiagnosticConsumer.h
|
||||
data/parser/cxx/CxxParser.cpp
|
||||
data/parser/cxx/CxxParser.h
|
||||
data/parser/cxx/utilityCxx.cpp
|
||||
|
||||
+5
-4
@@ -102,12 +102,13 @@ void Project::parseCode()
|
||||
);
|
||||
time = clock() - time;
|
||||
|
||||
m_storage->logGraph();
|
||||
m_storage->logLocations();
|
||||
// m_storage->logGraph();
|
||||
// m_storage->logLocations();
|
||||
|
||||
LOG_INFO_STREAM(<< "parse time: " << (double)(time) / CLOCKS_PER_SEC);
|
||||
double parseTime = (double)(time) / CLOCKS_PER_SEC;
|
||||
LOG_INFO_STREAM(<< "parse time: " << parseTime);
|
||||
|
||||
MessageFinishedParsing().dispatch();
|
||||
MessageFinishedParsing(parseTime, m_storage->getErrorCount()).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,34 @@ void CodeController::handleMessage(MessageActivateTokens* message)
|
||||
activeTokenIds = m_graphAccess->getActiveTokenIdsForId(activeTokenIds[0], &declarationId);
|
||||
}
|
||||
|
||||
getView()->setActiveTokenIds(activeTokenIds);
|
||||
getView()->showCodeSnippets(getSnippetsForActiveTokenIds(activeTokenIds, declarationId));
|
||||
CodeView* view = getView();
|
||||
view->setActiveTokenIds(activeTokenIds);
|
||||
view->setErrorMessages(std::vector<std::string>());
|
||||
view->showCodeSnippets(getSnippetsForActiveTokenIds(activeTokenIds, declarationId));
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
if (message->errorCount > 0)
|
||||
{
|
||||
std::vector<std::string> errorMessages;
|
||||
TokenLocationCollection errorCollection = m_locationAccess->getErrorTokenLocations(&errorMessages);
|
||||
|
||||
std::vector<CodeView::CodeSnippetParams> snippets;
|
||||
|
||||
errorCollection.forEachTokenLocationFile(
|
||||
[&](TokenLocationFile* file) -> void
|
||||
{
|
||||
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
|
||||
snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end());
|
||||
}
|
||||
);
|
||||
|
||||
CodeView* view = getView();
|
||||
view->setActiveTokenIds(std::vector<Id>());
|
||||
view->setErrorMessages(errorMessages);
|
||||
view->showCodeSnippets(snippets);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageRefresh* message)
|
||||
@@ -78,28 +104,12 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
||||
collection.forEachTokenLocationFile(
|
||||
[&](TokenLocationFile* file) -> void
|
||||
{
|
||||
const std::string filePath = file->getFilePath();
|
||||
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath);
|
||||
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
|
||||
|
||||
std::vector<std::pair<uint, uint>> ranges = getSnippetRangesForFile(file, s_lineRadius);
|
||||
std::vector<CodeView::CodeSnippetParams> fileSnippets;
|
||||
|
||||
for (const std::pair<uint, uint>& range: ranges)
|
||||
for (CodeView::CodeSnippetParams& params : fileSnippets)
|
||||
{
|
||||
unsigned int firstLineNumber = std::max<int>(1, range.first - s_lineRadius);
|
||||
unsigned int lastLineNumber = std::min<int>(textAccess->getLineCount(), range.second + s_lineRadius);
|
||||
|
||||
CodeView::CodeSnippetParams params;
|
||||
for (const std::string& line: textAccess->getLines(firstLineNumber, lastLineNumber))
|
||||
{
|
||||
params.code += line;
|
||||
}
|
||||
|
||||
params.startLineNumber = firstLineNumber;
|
||||
params.locationFile =
|
||||
m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber);
|
||||
|
||||
fileSnippets.push_back(params);
|
||||
params.locationFile = m_locationAccess->getTokenLocationsForLinesInFile(
|
||||
file->getFilePath(), params.startLineNumber, params.endLineNumber);
|
||||
}
|
||||
|
||||
if (declarationId != 0)
|
||||
@@ -133,9 +143,32 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
||||
return snippets;
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint, uint>> CodeController::getSnippetRangesForFile(
|
||||
TokenLocationFile* file, const uint lineRadius
|
||||
) const
|
||||
std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(const TokenLocationFile* file) const
|
||||
{
|
||||
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(file->getFilePath());
|
||||
|
||||
std::vector<std::pair<uint, uint>> ranges = getSnippetRangesForFile(file);
|
||||
std::vector<CodeView::CodeSnippetParams> snippets;
|
||||
|
||||
for (const std::pair<uint, uint>& range: ranges)
|
||||
{
|
||||
CodeView::CodeSnippetParams params;
|
||||
params.locationFile = *file;
|
||||
params.startLineNumber = std::max<int>(1, range.first - s_lineRadius);
|
||||
params.endLineNumber = std::min<int>(textAccess->getLineCount(), range.second + s_lineRadius);
|
||||
|
||||
for (const std::string& line: textAccess->getLines(params.startLineNumber, params.endLineNumber))
|
||||
{
|
||||
params.code += line;
|
||||
}
|
||||
|
||||
snippets.push_back(params);
|
||||
}
|
||||
|
||||
return snippets;
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint, uint>> CodeController::getSnippetRangesForFile(const TokenLocationFile* file) const
|
||||
{
|
||||
std::vector<std::pair<uint, uint>> ranges;
|
||||
uint start = 0;
|
||||
@@ -152,7 +185,7 @@ std::vector<std::pair<uint, uint>> CodeController::getSnippetRangesForFile(
|
||||
{
|
||||
start = lineNumber;
|
||||
}
|
||||
else if (end && lineNumber > end + 2 * lineRadius + 1)
|
||||
else if (end && lineNumber > end + 2 * s_lineRadius + 1)
|
||||
{
|
||||
ranges.push_back(std::make_pair(uint(start), uint(end)));
|
||||
start = lineNumber;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
#include "utility/messaging/type/MessageShowFile.h"
|
||||
#include "utility/types.h"
|
||||
@@ -20,6 +21,7 @@ class CodeController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateTokenLocation>
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageFinishedParsing>
|
||||
, public MessageListener<MessageRefresh>
|
||||
, public MessageListener<MessageShowFile>
|
||||
{
|
||||
@@ -32,6 +34,7 @@ private:
|
||||
|
||||
virtual void handleMessage(MessageActivateTokenLocation* message);
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
virtual void handleMessage(MessageRefresh* message);
|
||||
virtual void handleMessage(MessageShowFile* message);
|
||||
|
||||
@@ -39,7 +42,8 @@ private:
|
||||
|
||||
std::vector<CodeView::CodeSnippetParams> getSnippetsForActiveTokenIds(
|
||||
const std::vector<Id>& ids, Id declarationId) const;
|
||||
std::vector<std::pair<uint, uint>> getSnippetRangesForFile(TokenLocationFile* file, const uint lineRadius) const;
|
||||
std::vector<CodeView::CodeSnippetParams> getSnippetsForFile(const TokenLocationFile* file) const;
|
||||
std::vector<std::pair<uint, uint>> getSnippetRangesForFile(const TokenLocationFile* file) const;
|
||||
|
||||
GraphAccess* m_graphAccess;
|
||||
LocationAccess* m_locationAccess;
|
||||
|
||||
@@ -56,6 +56,11 @@ void GraphController::handleMessage(MessageActivateTokens* message)
|
||||
createDummyGraphForTokenIds(m_activeTokenIds);
|
||||
}
|
||||
|
||||
void GraphController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
getView()->clear();
|
||||
}
|
||||
|
||||
void GraphController::handleMessage(MessageGraphNodeExpand* message)
|
||||
{
|
||||
DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access);
|
||||
@@ -153,10 +158,26 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
|
||||
|
||||
Edge* edge = child->getMemberEdge();
|
||||
TokenComponentAccess* access = edge->getComponent<TokenComponentAccess>();
|
||||
TokenComponentAccess::AccessType accessType = TokenComponentAccess::ACCESS_NONE;
|
||||
|
||||
if (access)
|
||||
{
|
||||
TokenComponentAccess::AccessType accessType = access->getAccess();
|
||||
accessType = access->getAccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node->isType(Node::NODE_CLASS | Node::NODE_STRUCT))
|
||||
{
|
||||
accessType = TokenComponentAccess::ACCESS_PUBLIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = &result;
|
||||
}
|
||||
}
|
||||
|
||||
if (accessType != TokenComponentAccess::ACCESS_NONE)
|
||||
{
|
||||
for (DummyNode& dummy : result.subNodes)
|
||||
{
|
||||
if (dummy.accessType == accessType)
|
||||
@@ -178,10 +199,6 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = &result;
|
||||
}
|
||||
|
||||
parent->subNodes.push_back(createDummyNodeTopDown(child));
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeExpand.h"
|
||||
#include "utility/messaging/type/MessageGraphNodeMove.h"
|
||||
|
||||
@@ -21,6 +22,7 @@ class Node;
|
||||
class GraphController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageFinishedParsing>
|
||||
, public MessageListener<MessageGraphNodeExpand>
|
||||
, public MessageListener<MessageGraphNodeMove>
|
||||
{
|
||||
@@ -47,6 +49,7 @@ public:
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
virtual void handleMessage(MessageGraphNodeExpand* message);
|
||||
virtual void handleMessage(MessageGraphNodeMove* message);
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ void SearchController::handleMessage(MessageFind* message)
|
||||
getView()->setFocus();
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
getView()->setText("");
|
||||
}
|
||||
|
||||
void SearchController::handleMessage(MessageRefresh* message)
|
||||
{
|
||||
getView()->refreshView();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageFind.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
#include "utility/messaging/type/MessageSearch.h"
|
||||
#include "utility/messaging/type/MessageSearchAutocomplete.h"
|
||||
@@ -18,6 +19,7 @@ class SearchController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageFind>
|
||||
, public MessageListener<MessageFinishedParsing>
|
||||
, public MessageListener<MessageRefresh>
|
||||
, public MessageListener<MessageSearch>
|
||||
, public MessageListener<MessageSearchAutocomplete>
|
||||
@@ -29,6 +31,7 @@ public:
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
virtual void handleMessage(MessageFind* message);
|
||||
virtual void handleMessage(MessageFinishedParsing* message);
|
||||
virtual void handleMessage(MessageRefresh* message);
|
||||
virtual void handleMessage(MessageSearch* message);
|
||||
virtual void handleMessage(MessageSearchAutocomplete* message);
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include "component/view/StatusBarView.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
StatusBarController::StatusBarController()
|
||||
: MessageListener<MessageError>(true)
|
||||
, MessageListener<MessageFinishedParsing>(true)
|
||||
@@ -23,7 +26,14 @@ StatusBarView* StatusBarController::getView()
|
||||
|
||||
void StatusBarController::handleMessage(MessageFinishedParsing* message)
|
||||
{
|
||||
setStatus("Parsing Finished");
|
||||
std::stringstream ss;
|
||||
ss << "Parsing Finished: ";
|
||||
ss << std::setprecision(2) << message->parseTime << " seconds, ";
|
||||
ss << message->errorCount << " error(s)";
|
||||
|
||||
bool hasErrors = message->errorCount > 0;
|
||||
|
||||
setStatus(ss.str(), hasErrors);
|
||||
}
|
||||
|
||||
void StatusBarController::handleMessage(MessageStatus* message)
|
||||
|
||||
@@ -34,8 +34,9 @@ public:
|
||||
|
||||
virtual std::string getName() const;
|
||||
|
||||
virtual void clearCodeSnippets() = 0;
|
||||
virtual void setActiveTokenIds(const std::vector<Id>& activeTokenIds) = 0;
|
||||
virtual void setErrorMessages(const std::vector<std::string>& errorMessages) = 0;
|
||||
|
||||
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets) = 0;
|
||||
virtual void showCodeFile(const CodeSnippetParams& params) = 0;
|
||||
|
||||
|
||||
@@ -48,6 +48,30 @@ void Storage::logLocations() const
|
||||
LOG_INFO_STREAM(<< '\n' << m_locationCollection);
|
||||
}
|
||||
|
||||
size_t Storage::getErrorCount() const
|
||||
{
|
||||
return m_errorMessages.size();
|
||||
}
|
||||
|
||||
void Storage::onError(const ParseLocation& location, const std::string& message)
|
||||
{
|
||||
log("ERROR", message, location);
|
||||
|
||||
if (!location.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Id errorId = m_errorMessages.size();
|
||||
|
||||
TokenLocation* loc = m_errorLocationCollection.addTokenLocation(
|
||||
errorId, location.filePath,
|
||||
location.startLineNumber, location.startColumnNumber,
|
||||
location.endLineNumber, location.endColumnNumber
|
||||
);
|
||||
|
||||
m_errorMessages.push_back(message);
|
||||
}
|
||||
|
||||
Id Storage::onTypedefParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseTypeUsage& underlyingType,
|
||||
@@ -576,7 +600,6 @@ std::vector<Id> Storage::getActiveTokenIdsForId(Id tokenId, Id* declarationId) c
|
||||
|
||||
ret.push_back(token->getId());
|
||||
|
||||
Node* node;
|
||||
if (token->isNode())
|
||||
{
|
||||
Node* node = dynamic_cast<Node*>(token);
|
||||
@@ -744,6 +767,13 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile(
|
||||
return ret;
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getErrorTokenLocations(std::vector<std::string>* errorMessages) const
|
||||
{
|
||||
errorMessages->insert(errorMessages->begin(), m_errorMessages.begin(), m_errorMessages.end());
|
||||
|
||||
return m_errorLocationCollection;
|
||||
}
|
||||
|
||||
const Graph& Storage::getGraph() const
|
||||
{
|
||||
return m_graph;
|
||||
@@ -941,8 +971,16 @@ bool Storage::getSubQuerySearchResults(
|
||||
{
|
||||
if (word.size())
|
||||
{
|
||||
SearchResults res = node->runFuzzySearch(word);
|
||||
results->insert(res.begin(), res.end());
|
||||
if (searchNodes.size() > 1)
|
||||
{
|
||||
SearchResults res = node->runFuzzySearchOnSelf(word);
|
||||
results->insert(res.begin(), res.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
SearchResults res = node->runFuzzySearch(word);
|
||||
results->insert(res.begin(), res.end());
|
||||
}
|
||||
}
|
||||
else if (searchNodes.size() == 1)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,11 @@ public:
|
||||
void logGraph() const;
|
||||
void logLocations() const;
|
||||
|
||||
size_t getErrorCount() const;
|
||||
|
||||
// ParserClient implementation
|
||||
virtual void onError(const ParseLocation& location, const std::string& message);
|
||||
|
||||
virtual Id onTypedefParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
||||
const ParseTypeUsage& underlyingType, AccessType access);
|
||||
@@ -108,6 +112,8 @@ public:
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const;
|
||||
|
||||
protected:
|
||||
const Graph& getGraph() const;
|
||||
const TokenLocationCollection& getTokenLocationCollection() const;
|
||||
@@ -137,6 +143,9 @@ private:
|
||||
|
||||
SearchIndex m_tokenIndex;
|
||||
SearchIndex m_filterIndex;
|
||||
|
||||
TokenLocationCollection m_errorLocationCollection;
|
||||
std::vector<std::string> m_errorMessages;
|
||||
};
|
||||
|
||||
#endif // STORAGE_H
|
||||
|
||||
@@ -18,6 +18,8 @@ public:
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const = 0;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -60,3 +60,13 @@ TokenLocationFile LocationAccessProxy::getTokenLocationsForLinesInFile(
|
||||
|
||||
return TokenLocationFile("");
|
||||
}
|
||||
|
||||
TokenLocationCollection LocationAccessProxy::getErrorTokenLocations(std::vector<std::string>* errorMessages) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getErrorTokenLocations(errorMessages);
|
||||
}
|
||||
|
||||
return TokenLocationCollection();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ public:
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const;
|
||||
|
||||
private:
|
||||
LocationAccess* m_subject;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,19 @@ ParseLocation::ParseLocation()
|
||||
{
|
||||
}
|
||||
|
||||
ParseLocation::ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint lineNumber,
|
||||
uint columnNumber
|
||||
)
|
||||
: filePath(filePath)
|
||||
, startLineNumber(lineNumber)
|
||||
, startColumnNumber(columnNumber)
|
||||
, endLineNumber(lineNumber)
|
||||
, endColumnNumber(columnNumber)
|
||||
{
|
||||
}
|
||||
|
||||
ParseLocation::ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint startLineNumber, uint startColumnNumber,
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
struct ParseLocation
|
||||
{
|
||||
ParseLocation();
|
||||
ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint lineNumber,
|
||||
uint columnNumber
|
||||
);
|
||||
ParseLocation(
|
||||
const std::string& filePath,
|
||||
uint startLineNumber, uint startColumnNumber,
|
||||
|
||||
@@ -49,6 +49,8 @@ public:
|
||||
ParserClient();
|
||||
virtual ~ParserClient();
|
||||
|
||||
virtual void onError(const ParseLocation& location, const std::string& message) = 0;
|
||||
|
||||
virtual Id onTypedefParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
||||
const ParseTypeUsage& underlyingType, AccessType access) = 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "data/parser/cxx/ASTConsumer.h"
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client)
|
||||
: m_visitor(context, client)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
|
||||
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
||||
#include "data/parser/ParseLocation.h"
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
CxxDiagnosticConsumer::CxxDiagnosticConsumer(
|
||||
clang::raw_ostream &os,
|
||||
clang::DiagnosticOptions *diags,
|
||||
ParserClient* client,
|
||||
bool useLogging
|
||||
)
|
||||
: clang::TextDiagnosticPrinter(os, diags)
|
||||
, m_client(client)
|
||||
, m_isParsingFile(false)
|
||||
, m_useLogging(useLogging)
|
||||
{
|
||||
}
|
||||
|
||||
void CxxDiagnosticConsumer::BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor)
|
||||
{
|
||||
if (m_useLogging)
|
||||
{
|
||||
clang::TextDiagnosticPrinter::BeginSourceFile(langOptions, preProcessor);
|
||||
}
|
||||
|
||||
m_isParsingFile = true;
|
||||
}
|
||||
|
||||
void CxxDiagnosticConsumer::EndSourceFile()
|
||||
{
|
||||
if (m_useLogging)
|
||||
{
|
||||
clang::TextDiagnosticPrinter::EndSourceFile();
|
||||
}
|
||||
|
||||
m_isParsingFile = false;
|
||||
}
|
||||
|
||||
void CxxDiagnosticConsumer::HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info)
|
||||
{
|
||||
if (m_useLogging)
|
||||
{
|
||||
clang::TextDiagnosticPrinter::HandleDiagnostic(level, info);
|
||||
}
|
||||
|
||||
if (!m_isParsingFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (level == clang::DiagnosticsEngine::Error || level == clang::DiagnosticsEngine::Fatal)
|
||||
{
|
||||
llvm::SmallString<100> messageStr;
|
||||
info.FormatDiagnostic(messageStr);
|
||||
std::string message = messageStr.str();
|
||||
|
||||
std::string filePath;
|
||||
uint line = 0;
|
||||
uint column = 0;
|
||||
|
||||
if (info.getLocation().isValid() && info.hasSourceManager())
|
||||
{
|
||||
const clang::SourceManager& sourceManager = info.getSourceManager();
|
||||
clang::PresumedLoc presumedLocation = sourceManager.getPresumedLoc(info.getLocation());
|
||||
|
||||
filePath = presumedLocation.getFilename();
|
||||
line = presumedLocation.getLine();
|
||||
column = presumedLocation.getColumn();
|
||||
}
|
||||
|
||||
m_client->onError(ParseLocation(filePath, line, column), message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef CXX_DIAGNOSTIC_CONSUMER
|
||||
#define CXX_DIAGNOSTIC_CONSUMER
|
||||
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
|
||||
class ParserClient;
|
||||
|
||||
class CxxDiagnosticConsumer
|
||||
: public clang::TextDiagnosticPrinter
|
||||
{
|
||||
public:
|
||||
CxxDiagnosticConsumer(clang::raw_ostream &os, clang::DiagnosticOptions *diags, ParserClient* client, bool useLogging = true);
|
||||
|
||||
void BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor);
|
||||
void EndSourceFile();
|
||||
|
||||
void HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info);
|
||||
|
||||
private:
|
||||
ParserClient* m_client;
|
||||
bool m_isParsingFile;
|
||||
bool m_useLogging;
|
||||
};
|
||||
|
||||
#endif // CXX_DIAGNOSTIC_CONSUMER
|
||||
@@ -1,9 +1,54 @@
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
|
||||
#include "data/parser/cxx/ASTActionFactory.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
|
||||
#include "data/parser/cxx/ASTActionFactory.h"
|
||||
#include "data/parser/cxx/CxxDiagnosticConsumer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static std::vector<std::string> getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs, llvm::StringRef FileName)
|
||||
{
|
||||
std::vector<std::string> Args;
|
||||
Args.push_back("clang-tool");
|
||||
Args.push_back("-fsyntax-only");
|
||||
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
|
||||
Args.push_back(FileName.str());
|
||||
return Args;
|
||||
}
|
||||
|
||||
// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer
|
||||
static bool runToolOnCodeWithArgs(
|
||||
clang::DiagnosticConsumer* DiagConsumer,
|
||||
clang::FrontendAction *ToolAction,
|
||||
const llvm::Twine &Code,
|
||||
const std::vector<std::string> &Args,
|
||||
const llvm::Twine &FileName = "input.cc",
|
||||
const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings()
|
||||
){
|
||||
llvm::SmallString<16> FileNameStorage;
|
||||
llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
|
||||
llvm::IntrusiveRefCntPtr<clang::FileManager> Files(new clang::FileManager(clang::FileSystemOptions()));
|
||||
clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get());
|
||||
|
||||
llvm::SmallString<1024> CodeStorage;
|
||||
Invocation.mapVirtualFile(FileNameRef,
|
||||
Code.toNullTerminatedStringRef(CodeStorage));
|
||||
|
||||
for (auto &FilenameWithContent : VirtualMappedFiles)
|
||||
{
|
||||
Invocation.mapVirtualFile(FilenameWithContent.first,
|
||||
FilenameWithContent.second);
|
||||
}
|
||||
|
||||
Invocation.setDiagnosticConsumer(DiagConsumer);
|
||||
|
||||
return Invocation.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CxxParser::CxxParser(ParserClient* client)
|
||||
: Parser(client)
|
||||
{
|
||||
@@ -68,15 +113,22 @@ void CxxParser::parseFiles(
|
||||
|
||||
clang::tooling::ClangTool tool(*compilationDatabase, filePaths);
|
||||
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
|
||||
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client);
|
||||
tool.setDiagnosticConsumer(&reporter);
|
||||
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
tool.run(&actionFactory);
|
||||
}
|
||||
|
||||
void CxxParser::parseFile(std::shared_ptr<TextAccess> textAccess)
|
||||
{
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
std::vector<std::string> args;
|
||||
args.push_back("-fno-delayed-template-parsing");
|
||||
clang::tooling::runToolOnCodeWithArgs(actionFactory.create(), textAccess->getText(), args);
|
||||
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
|
||||
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, false);
|
||||
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args);
|
||||
}
|
||||
|
||||
@@ -107,6 +107,20 @@ SearchResults SearchNode::runFuzzySearch(const std::string& query) const
|
||||
return result;
|
||||
}
|
||||
|
||||
SearchResults SearchNode::runFuzzySearchOnSelf(const std::string& query) const
|
||||
{
|
||||
SearchResults result;
|
||||
FuzzyMap m = fuzzyMatchRecursive(query, 0, 0, 0);
|
||||
for (const std::pair<size_t, const SearchNode*>& p : m)
|
||||
{
|
||||
addResultsRecursive(result, p.first, p.second);
|
||||
}
|
||||
|
||||
// TODO: Currently all matches are added to the ordered set and get compared by their fullName for alphabetical
|
||||
// order. This could be improved by limiting the number of items to e.g. 100.
|
||||
return result;
|
||||
}
|
||||
|
||||
void SearchNode::addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const
|
||||
{
|
||||
result.insert(SearchResult(weight, node, this));
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
const std::set<std::shared_ptr<SearchNode>>& getChildren() const;
|
||||
|
||||
SearchResults runFuzzySearch(const std::string& query) const;
|
||||
SearchResults runFuzzySearchOnSelf(const std::string& query) const;
|
||||
|
||||
void addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
class MessageFinishedParsing: public Message<MessageFinishedParsing>
|
||||
{
|
||||
public:
|
||||
MessageFinishedParsing()
|
||||
MessageFinishedParsing(float parseTime, size_t errorCount)
|
||||
: parseTime(parseTime)
|
||||
, errorCount(errorCount)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -14,6 +16,9 @@ public:
|
||||
{
|
||||
return "MessageFinishedParsing";
|
||||
}
|
||||
|
||||
float parseTime;
|
||||
size_t errorCount;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_FINISHED_PARSING_H
|
||||
|
||||
Reference in New Issue
Block a user