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:
@@ -14,6 +14,9 @@ int main()
|
|||||||
int a = sum(1, 2);
|
int a = sum(1, 2);
|
||||||
int b = diff(a, 3);
|
int b = diff(a, 3);
|
||||||
int c = a * b;
|
int c = a * b;
|
||||||
|
|
||||||
|
int x = y;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "qt/element/QtCodeFileList.h"
|
||||||
#include "qt/element/QtCodeSnippet.h"
|
#include "qt/element/QtCodeSnippet.h"
|
||||||
#include "utility/FileSystem.h"
|
#include "utility/FileSystem.h"
|
||||||
|
|
||||||
QtCodeFile::QtCodeFile(const std::string& filePath, QWidget *parent)
|
QtCodeFile::QtCodeFile(const std::string& filePath, QtCodeFileList* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
, m_parent(parent)
|
||||||
, m_filePath(filePath)
|
, m_filePath(filePath)
|
||||||
, m_showMaximizeButton(true)
|
|
||||||
{
|
{
|
||||||
setObjectName("code_file");
|
setObjectName("code_file");
|
||||||
|
|
||||||
@@ -31,21 +32,35 @@ QtCodeFile::~QtCodeFile()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& QtCodeFile::getFilePath() const
|
||||||
|
{
|
||||||
|
return m_filePath;
|
||||||
|
}
|
||||||
|
|
||||||
std::string QtCodeFile::getFileName() const
|
std::string QtCodeFile::getFileName() const
|
||||||
{
|
{
|
||||||
return FileSystem::fileName(m_filePath);
|
return FileSystem::fileName(m_filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<Id>& QtCodeFile::getActiveTokenIds() const
|
||||||
|
{
|
||||||
|
return m_parent->getActiveTokenIds();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& QtCodeFile::getErrorMessages() const
|
||||||
|
{
|
||||||
|
return m_parent->getErrorMessages();
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeFile::addCodeSnippet(
|
void QtCodeFile::addCodeSnippet(
|
||||||
uint startLineNumber,
|
uint startLineNumber,
|
||||||
const std::string& code,
|
const std::string& code,
|
||||||
const TokenLocationFile& locationFile,
|
const TokenLocationFile& locationFile
|
||||||
const std::vector<Id>& activeTokenIds
|
|
||||||
){
|
){
|
||||||
std::shared_ptr<QtCodeSnippet> snippet(
|
std::shared_ptr<QtCodeSnippet> snippet(
|
||||||
new QtCodeSnippet(startLineNumber, code, locationFile, activeTokenIds, this));
|
new QtCodeSnippet(startLineNumber, code, locationFile, this));
|
||||||
|
|
||||||
if (m_showMaximizeButton)
|
if (m_parent->getShowMaximizeButton())
|
||||||
{
|
{
|
||||||
snippet->addMaximizeButton();
|
snippet->addMaximizeButton();
|
||||||
}
|
}
|
||||||
@@ -65,15 +80,10 @@ void QtCodeFile::addCodeSnippet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeFile::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
void QtCodeFile::update()
|
||||||
{
|
{
|
||||||
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
|
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
|
||||||
{
|
{
|
||||||
snippet->setActiveTokenIds(activeTokenIds);
|
snippet->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeFile::setShowMaximizeButton(bool show)
|
|
||||||
{
|
|
||||||
m_showMaximizeButton = show;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,31 +9,34 @@
|
|||||||
|
|
||||||
#include "utility/types.h"
|
#include "utility/types.h"
|
||||||
|
|
||||||
|
class QtCodeFileList;
|
||||||
class QtCodeSnippet;
|
class QtCodeSnippet;
|
||||||
class TokenLocationFile;
|
class TokenLocationFile;
|
||||||
|
|
||||||
class QtCodeFile : public QWidget
|
class QtCodeFile : public QWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QtCodeFile(const std::string& filePath, QWidget *parent = 0);
|
QtCodeFile(const std::string& filePath, QtCodeFileList* parent);
|
||||||
virtual ~QtCodeFile();
|
virtual ~QtCodeFile();
|
||||||
|
|
||||||
|
const std::string& getFilePath() const;
|
||||||
std::string getFileName() const;
|
std::string getFileName() const;
|
||||||
|
const std::vector<Id>& getActiveTokenIds() const;
|
||||||
|
const std::vector<std::string>& getErrorMessages() const;
|
||||||
|
|
||||||
void addCodeSnippet(
|
void addCodeSnippet(
|
||||||
uint startLineNumber,
|
uint startLineNumber,
|
||||||
const std::string& code,
|
const std::string& code,
|
||||||
const TokenLocationFile& locationFile,
|
const TokenLocationFile& locationFile
|
||||||
const std::vector<Id>& activeTokenIds
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
|
void update();
|
||||||
void setShowMaximizeButton(bool show);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<QtCodeSnippet> > m_snippets;
|
QtCodeFileList* m_parent;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<QtCodeSnippet>> m_snippets;
|
||||||
const std::string m_filePath;
|
const std::string m_filePath;
|
||||||
bool m_showMaximizeButton;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_CODE_FILE_H
|
#endif // QT_CODE_FILE_H
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ QSize QtCodeFileList::sizeHint() const
|
|||||||
void QtCodeFileList::addCodeSnippet(
|
void QtCodeFileList::addCodeSnippet(
|
||||||
uint startLineNumber,
|
uint startLineNumber,
|
||||||
const std::string& code,
|
const std::string& code,
|
||||||
const TokenLocationFile& locationFile,
|
const TokenLocationFile& locationFile
|
||||||
const std::vector<Id>& activeTokenIds
|
|
||||||
){
|
){
|
||||||
std::string fileName = FileSystem::fileName(locationFile.getFilePath());
|
std::string fileName = FileSystem::fileName(locationFile.getFilePath());
|
||||||
QtCodeFile* file = nullptr;
|
QtCodeFile* file = nullptr;
|
||||||
@@ -58,11 +57,9 @@ void QtCodeFileList::addCodeSnippet(
|
|||||||
|
|
||||||
file = filePtr.get();
|
file = filePtr.get();
|
||||||
m_frame->layout()->addWidget(file);
|
m_frame->layout()->addWidget(file);
|
||||||
|
|
||||||
file->setShowMaximizeButton(m_showMaximizeButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file->addCodeSnippet(startLineNumber, code, locationFile, activeTokenIds);
|
file->addCodeSnippet(startLineNumber, code, locationFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeFileList::clearCodeSnippets()
|
void QtCodeFileList::clearCodeSnippets()
|
||||||
@@ -70,15 +67,43 @@ void QtCodeFileList::clearCodeSnippets()
|
|||||||
m_files.clear();
|
m_files.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<Id>& QtCodeFileList::getActiveTokenIds() const
|
||||||
|
{
|
||||||
|
return m_activeTokenIds;
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeFileList::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
void QtCodeFileList::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
||||||
{
|
{
|
||||||
for (std::shared_ptr<QtCodeFile> file: m_files)
|
m_activeTokenIds = activeTokenIds;
|
||||||
{
|
updateFiles();
|
||||||
file->setActiveTokenIds(activeTokenIds);
|
}
|
||||||
}
|
|
||||||
|
const std::vector<std::string>& QtCodeFileList::getErrorMessages() const
|
||||||
|
{
|
||||||
|
return m_errorMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtCodeFileList::setErrorMessages(const std::vector<std::string>& errorMessages)
|
||||||
|
{
|
||||||
|
m_errorMessages = errorMessages;
|
||||||
|
updateFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtCodeFileList::getShowMaximizeButton() const
|
||||||
|
{
|
||||||
|
return m_showMaximizeButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeFileList::setShowMaximizeButton(bool show)
|
void QtCodeFileList::setShowMaximizeButton(bool show)
|
||||||
{
|
{
|
||||||
m_showMaximizeButton = show;
|
m_showMaximizeButton = show;
|
||||||
|
updateFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtCodeFileList::updateFiles()
|
||||||
|
{
|
||||||
|
for (std::shared_ptr<QtCodeFile> file: m_files)
|
||||||
|
{
|
||||||
|
file->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,19 +25,28 @@ public:
|
|||||||
void addCodeSnippet(
|
void addCodeSnippet(
|
||||||
uint startLineNumber,
|
uint startLineNumber,
|
||||||
const std::string& code,
|
const std::string& code,
|
||||||
const TokenLocationFile& locationFile,
|
const TokenLocationFile& locationFile
|
||||||
const std::vector<Id>& activeTokenIds
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void clearCodeSnippets();
|
void clearCodeSnippets();
|
||||||
|
|
||||||
|
const std::vector<Id>& getActiveTokenIds() const;
|
||||||
void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
|
void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
|
||||||
|
|
||||||
|
const std::vector<std::string>& getErrorMessages() const;
|
||||||
|
void setErrorMessages(const std::vector<std::string>& errorMessages);
|
||||||
|
|
||||||
|
bool getShowMaximizeButton() const;
|
||||||
void setShowMaximizeButton(bool show);
|
void setShowMaximizeButton(bool show);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<QFrame> m_frame;
|
void updateFiles();
|
||||||
std::vector<std::shared_ptr<QtCodeFile> > m_files;
|
|
||||||
|
|
||||||
|
std::shared_ptr<QFrame> m_frame;
|
||||||
|
std::vector<std::shared_ptr<QtCodeFile>> m_files;
|
||||||
|
|
||||||
|
std::vector<Id> m_activeTokenIds;
|
||||||
|
std::vector<std::string> m_errorMessages;
|
||||||
bool m_showMaximizeButton;
|
bool m_showMaximizeButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QToolTip>
|
||||||
|
|
||||||
#include "ApplicationSettings.h"
|
#include "ApplicationSettings.h"
|
||||||
#include "data/location/TokenLocation.h"
|
#include "data/location/TokenLocation.h"
|
||||||
#include "data/location/TokenLocationFile.h"
|
#include "data/location/TokenLocationFile.h"
|
||||||
|
#include "qt/element/QtCodeFile.h"
|
||||||
#include "qt/utility/QtHighlighter.h"
|
#include "qt/utility/QtHighlighter.h"
|
||||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||||
#include "utility/messaging/type/MessageShowFile.h"
|
#include "utility/messaging/type/MessageShowFile.h"
|
||||||
@@ -38,14 +40,13 @@ QtCodeSnippet::QtCodeSnippet(
|
|||||||
uint startLineNumber,
|
uint startLineNumber,
|
||||||
const std::string& code,
|
const std::string& code,
|
||||||
const TokenLocationFile& locationFile,
|
const TokenLocationFile& locationFile,
|
||||||
const std::vector<Id>& activeTokenIds,
|
QtCodeFile* parent
|
||||||
QWidget *parent
|
|
||||||
)
|
)
|
||||||
: QPlainTextEdit(parent)
|
: QPlainTextEdit(parent)
|
||||||
|
, m_parent(parent)
|
||||||
, m_maximizeButton(nullptr)
|
, m_maximizeButton(nullptr)
|
||||||
, m_startLineNumber(startLineNumber)
|
, m_startLineNumber(startLineNumber)
|
||||||
, m_filePath(locationFile.getFilePath())
|
, m_hoveredAnnotation(nullptr)
|
||||||
, m_activeTokenIds(activeTokenIds)
|
|
||||||
, m_digits(0)
|
, m_digits(0)
|
||||||
{
|
{
|
||||||
setObjectName("code_snippet");
|
setObjectName("code_snippet");
|
||||||
@@ -73,8 +74,9 @@ QtCodeSnippet::QtCodeSnippet(
|
|||||||
|
|
||||||
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||||
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
|
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
|
||||||
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(clickedTokenLocation()));
|
|
||||||
connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection()));
|
connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection()));
|
||||||
|
|
||||||
|
this->setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtCodeSnippet::~QtCodeSnippet()
|
QtCodeSnippet::~QtCodeSnippet()
|
||||||
@@ -154,9 +156,8 @@ void QtCodeSnippet::updateLineNumberAreaWidthForDigits(int digits)
|
|||||||
updateLineNumberAreaWidth(0);
|
updateLineNumberAreaWidth(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeSnippet::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
void QtCodeSnippet::update()
|
||||||
{
|
{
|
||||||
m_activeTokenIds = activeTokenIds;
|
|
||||||
annotateText();
|
annotateText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,14 +193,52 @@ void QtCodeSnippet::leaveEvent(QEvent* event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtCodeSnippet::mouseReleaseEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
QTextCursor cursor = this->cursorForPosition(event->pos());
|
||||||
|
const Annotation* annotation = findAnnotationForPosition(cursor.position());
|
||||||
|
|
||||||
|
if (annotation)
|
||||||
|
{
|
||||||
|
MessageActivateTokenLocation(annotation->locationId).dispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeSnippet::mouseDoubleClickEvent(QMouseEvent* event)
|
void QtCodeSnippet::mouseDoubleClickEvent(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
if (m_maximizeButton)
|
if (event->button() == Qt::LeftButton && m_maximizeButton)
|
||||||
{
|
{
|
||||||
clickedMaximizeButton();
|
clickedMaximizeButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtCodeSnippet::mouseMoveEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
QTextCursor cursor = this->cursorForPosition(event->pos());
|
||||||
|
const Annotation* annotation = findAnnotationForPosition(cursor.position());
|
||||||
|
|
||||||
|
if (annotation != nullptr ? annotation != m_hoveredAnnotation && !annotation->isScope : m_hoveredAnnotation != nullptr)
|
||||||
|
{
|
||||||
|
m_hoveredAnnotation = annotation;
|
||||||
|
|
||||||
|
const std::vector<std::string>& errorMessages = m_parent->getErrorMessages();
|
||||||
|
|
||||||
|
if (annotation && errorMessages.size() > annotation->tokenId)
|
||||||
|
{
|
||||||
|
QToolTip::showText(event->globalPos(), QString::fromStdString(m_parent->getErrorMessages()[annotation->tokenId]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QToolTip::hideText();
|
||||||
|
}
|
||||||
|
|
||||||
|
annotateText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeSnippet::updateLineNumberAreaWidth(int /* newBlockCount */)
|
void QtCodeSnippet::updateLineNumberAreaWidth(int /* newBlockCount */)
|
||||||
{
|
{
|
||||||
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
|
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
|
||||||
@@ -222,34 +261,9 @@ void QtCodeSnippet::updateLineNumberArea(const QRect &rect, int dy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeSnippet::clickedTokenLocation()
|
|
||||||
{
|
|
||||||
int clickPosition = textCursor().position();
|
|
||||||
int diff = endTextEditPosition() + 1;
|
|
||||||
Id locationId = 0;
|
|
||||||
|
|
||||||
for (Annotation annotation : m_annotations)
|
|
||||||
{
|
|
||||||
if (clickPosition >= annotation.start && clickPosition <= annotation.end)
|
|
||||||
{
|
|
||||||
int d = annotation.end - annotation.start;
|
|
||||||
if (d < diff)
|
|
||||||
{
|
|
||||||
diff = d;
|
|
||||||
locationId = annotation.locationId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locationId)
|
|
||||||
{
|
|
||||||
MessageActivateTokenLocation(locationId).dispatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtCodeSnippet::clickedMaximizeButton()
|
void QtCodeSnippet::clickedMaximizeButton()
|
||||||
{
|
{
|
||||||
MessageShowFile(m_filePath, m_startLineNumber, m_startLineNumber + document()->blockCount() - 1).dispatch();
|
MessageShowFile(m_parent->getFilePath(), m_startLineNumber, m_startLineNumber + blockCount() - 1).dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeSnippet::clearSelection()
|
void QtCodeSnippet::clearSelection()
|
||||||
@@ -259,12 +273,33 @@ void QtCodeSnippet::clearSelection()
|
|||||||
setTextCursor(cursor);
|
setTextCursor(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QtCodeSnippet::Annotation* QtCodeSnippet::findAnnotationForPosition(int pos) const
|
||||||
|
{
|
||||||
|
const Annotation* annotationPtr = nullptr;
|
||||||
|
int diff = endTextEditPosition() + 1;
|
||||||
|
|
||||||
|
for (const Annotation& annotation : m_annotations)
|
||||||
|
{
|
||||||
|
if (pos >= annotation.start && pos <= annotation.end)
|
||||||
|
{
|
||||||
|
int d = annotation.end - annotation.start;
|
||||||
|
if (d < diff)
|
||||||
|
{
|
||||||
|
diff = d;
|
||||||
|
annotationPtr = &annotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return annotationPtr;
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile)
|
void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile)
|
||||||
{
|
{
|
||||||
locationFile.forEachTokenLocation(
|
locationFile.forEachTokenLocation(
|
||||||
[&](TokenLocation* location)
|
[&](TokenLocation* location)
|
||||||
{
|
{
|
||||||
if (location->isEndTokenLocation() && location->getStartTokenLocation())
|
if (!locationBelongsToSnippet(location))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -301,14 +336,27 @@ void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile)
|
|||||||
void QtCodeSnippet::annotateText()
|
void QtCodeSnippet::annotateText()
|
||||||
{
|
{
|
||||||
Colori color;
|
Colori color;
|
||||||
const std::vector<Id>& ids = m_activeTokenIds;
|
const std::vector<Id>& ids = m_parent->getActiveTokenIds();
|
||||||
|
const std::vector<std::string>& errorMessages = m_parent->getErrorMessages();
|
||||||
QList<QTextEdit::ExtraSelection> extraSelections;
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
||||||
|
|
||||||
for (const Annotation& annotation: m_annotations)
|
for (const Annotation& annotation: m_annotations)
|
||||||
{
|
{
|
||||||
bool isActive = std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end();
|
bool isActive = std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end();
|
||||||
|
|
||||||
if (isActive)
|
if (&annotation == m_hoveredAnnotation && errorMessages.size())
|
||||||
|
{
|
||||||
|
color = Colori(255, 0, 0, 128);
|
||||||
|
}
|
||||||
|
else if (&annotation == m_hoveredAnnotation)
|
||||||
|
{
|
||||||
|
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||||
|
}
|
||||||
|
else if (errorMessages.size())
|
||||||
|
{
|
||||||
|
color = Colori(255, 0, 0, 255);
|
||||||
|
}
|
||||||
|
else if (isActive)
|
||||||
{
|
{
|
||||||
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||||
}
|
}
|
||||||
@@ -335,6 +383,43 @@ void QtCodeSnippet::annotateText()
|
|||||||
setExtraSelections(extraSelections);
|
setExtraSelections(extraSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QtCodeSnippet::locationBelongsToSnippet(TokenLocation* location) const
|
||||||
|
{
|
||||||
|
uint lineNumber = location->getLineNumber();
|
||||||
|
|
||||||
|
if (location->isEndTokenLocation())
|
||||||
|
{
|
||||||
|
if (location->getStartTokenLocation() ||
|
||||||
|
lineNumber < m_startLineNumber || lineNumber >= m_startLineNumber + blockCount())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineNumber >= m_startLineNumber + blockCount())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineNumber >= m_startLineNumber)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenLocation* endLocation = location->getEndTokenLocation();
|
||||||
|
|
||||||
|
if (endLocation && endLocation->getLineNumber() < m_startLineNumber)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int QtCodeSnippet::toTextEditPosition(int lineNumber, int columnNumber) const
|
int QtCodeSnippet::toTextEditPosition(int lineNumber, int columnNumber) const
|
||||||
{
|
{
|
||||||
lineNumber -= m_startLineNumber - 1;
|
lineNumber -= m_startLineNumber - 1;
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ class QPaintEvent;
|
|||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QResizeEvent;
|
class QResizeEvent;
|
||||||
class QSize;
|
class QSize;
|
||||||
|
class QtCodeFile;
|
||||||
class QtHighlighter;
|
class QtHighlighter;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
class TokenLocation;
|
||||||
class TokenLocationFile;
|
class TokenLocationFile;
|
||||||
|
|
||||||
class QtCodeSnippet: public QPlainTextEdit
|
class QtCodeSnippet: public QPlainTextEdit
|
||||||
@@ -39,8 +41,7 @@ public:
|
|||||||
uint startLineNumber,
|
uint startLineNumber,
|
||||||
const std::string& code,
|
const std::string& code,
|
||||||
const TokenLocationFile& locationFile,
|
const TokenLocationFile& locationFile,
|
||||||
const std::vector<Id>& activeTokenIds,
|
QtCodeFile* parent
|
||||||
QWidget *parent = 0
|
|
||||||
);
|
);
|
||||||
virtual ~QtCodeSnippet();
|
virtual ~QtCodeSnippet();
|
||||||
|
|
||||||
@@ -53,19 +54,20 @@ public:
|
|||||||
int lineNumberAreaWidth() const;
|
int lineNumberAreaWidth() const;
|
||||||
void updateLineNumberAreaWidthForDigits(int digits);
|
void updateLineNumberAreaWidthForDigits(int digits);
|
||||||
|
|
||||||
void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
|
void update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void resizeEvent(QResizeEvent *event);
|
virtual void resizeEvent(QResizeEvent *event);
|
||||||
virtual void showEvent(QShowEvent* event);
|
virtual void showEvent(QShowEvent* event);
|
||||||
virtual void enterEvent(QEvent* event);
|
virtual void enterEvent(QEvent* event);
|
||||||
virtual void leaveEvent(QEvent* event);
|
virtual void leaveEvent(QEvent* event);
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent* event);
|
||||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
||||||
|
virtual void mouseMoveEvent(QMouseEvent* event);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateLineNumberAreaWidth(int newBlockCount);
|
void updateLineNumberAreaWidth(int newBlockCount);
|
||||||
void updateLineNumberArea(const QRect &, int);
|
void updateLineNumberArea(const QRect &, int);
|
||||||
void clickedTokenLocation();
|
|
||||||
void clickedMaximizeButton();
|
void clickedMaximizeButton();
|
||||||
void clearSelection();
|
void clearSelection();
|
||||||
|
|
||||||
@@ -79,24 +81,28 @@ private:
|
|||||||
bool isScope;
|
bool isScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Annotation* findAnnotationForPosition(int pos) const;
|
||||||
void createAnnotations(const TokenLocationFile& locationFile);
|
void createAnnotations(const TokenLocationFile& locationFile);
|
||||||
void annotateText();
|
void annotateText();
|
||||||
|
|
||||||
|
bool locationBelongsToSnippet(TokenLocation* location) const;
|
||||||
|
|
||||||
int toTextEditPosition(int lineNumber, int columnNumber) const;
|
int toTextEditPosition(int lineNumber, int columnNumber) const;
|
||||||
int startTextEditPosition() const;
|
int startTextEditPosition() const;
|
||||||
int endTextEditPosition() const;
|
int endTextEditPosition() const;
|
||||||
|
|
||||||
|
QtCodeFile* m_parent;
|
||||||
|
|
||||||
QWidget* m_lineNumberArea;
|
QWidget* m_lineNumberArea;
|
||||||
QtHighlighter* m_highlighter;
|
QtHighlighter* m_highlighter;
|
||||||
|
|
||||||
QPushButton* m_maximizeButton;
|
QPushButton* m_maximizeButton;
|
||||||
bool m_showMaximizeButton;
|
|
||||||
|
|
||||||
const uint m_startLineNumber;
|
const uint m_startLineNumber;
|
||||||
const std::string m_filePath;
|
|
||||||
std::vector<Id> m_activeTokenIds;
|
|
||||||
|
|
||||||
std::vector<Annotation> m_annotations;
|
std::vector<Annotation> m_annotations;
|
||||||
|
const Annotation* m_hoveredAnnotation;
|
||||||
|
|
||||||
int m_digits;
|
int m_digits;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,5 +17,10 @@ void QtStatusBar::setText(const std::string& text, bool isError)
|
|||||||
{
|
{
|
||||||
m_text.setStyleSheet("QLabel { color: red }");
|
m_text.setStyleSheet("QLabel { color: red }");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_text.setStyleSheet("");
|
||||||
|
}
|
||||||
|
|
||||||
m_text.setText(text.c_str());
|
m_text.setText(text.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
QtCodeView::QtCodeView(ViewLayout* viewLayout)
|
QtCodeView::QtCodeView(ViewLayout* viewLayout)
|
||||||
: CodeView(viewLayout)
|
: CodeView(viewLayout)
|
||||||
, m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this))
|
, m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this))
|
||||||
, m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this))
|
|
||||||
, m_showCodeSnippetsFunctor(std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1))
|
, m_showCodeSnippetsFunctor(std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1))
|
||||||
, m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1))
|
, m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1))
|
||||||
{
|
{
|
||||||
@@ -35,16 +34,16 @@ void QtCodeView::refreshView()
|
|||||||
m_refreshViewFunctor();
|
m_refreshViewFunctor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeView::clearCodeSnippets()
|
|
||||||
{
|
|
||||||
m_clearCodeSnippetsFunctor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtCodeView::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
void QtCodeView::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
|
||||||
{
|
{
|
||||||
m_activeTokenIds = activeTokenIds;
|
m_activeTokenIds = activeTokenIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtCodeView::setErrorMessages(const std::vector<std::string>& errorMessages)
|
||||||
|
{
|
||||||
|
m_errorMessages = errorMessages;
|
||||||
|
}
|
||||||
|
|
||||||
void QtCodeView::showCodeSnippets(const std::vector<CodeSnippetParams>& snippets)
|
void QtCodeView::showCodeSnippets(const std::vector<CodeSnippetParams>& snippets)
|
||||||
{
|
{
|
||||||
m_showCodeSnippetsFunctor(snippets);
|
m_showCodeSnippetsFunctor(snippets);
|
||||||
@@ -66,24 +65,31 @@ void QtCodeView::doRefreshView()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCodeView::doClearCodeSnippets()
|
|
||||||
{
|
|
||||||
m_widget->clearCodeSnippets();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtCodeView::doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets)
|
void QtCodeView::doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets)
|
||||||
{
|
{
|
||||||
doClearCodeSnippets();
|
m_widget->clearCodeSnippets();
|
||||||
|
|
||||||
clearClosedWindows();
|
clearClosedWindows();
|
||||||
for (std::shared_ptr<QtCodeFileList> window: m_windows)
|
for (std::shared_ptr<QtCodeFileList> window: m_windows)
|
||||||
{
|
{
|
||||||
window->setActiveTokenIds(m_activeTokenIds);
|
if (m_errorMessages.size())
|
||||||
|
{
|
||||||
|
window->close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->setActiveTokenIds(m_activeTokenIds);
|
||||||
|
window->setErrorMessages(m_errorMessages);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_widget->setActiveTokenIds(m_activeTokenIds);
|
||||||
|
m_widget->setErrorMessages(m_errorMessages);
|
||||||
|
m_widget->setShowMaximizeButton(m_errorMessages.size() == 0);
|
||||||
|
|
||||||
for (const CodeSnippetParams& params : snippets)
|
for (const CodeSnippetParams& params : snippets)
|
||||||
{
|
{
|
||||||
m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, m_activeTokenIds);
|
m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +99,9 @@ void QtCodeView::doShowCodeFile(const CodeSnippetParams& params)
|
|||||||
m_windows.push_back(ptr);
|
m_windows.push_back(ptr);
|
||||||
|
|
||||||
ptr->setShowMaximizeButton(false);
|
ptr->setShowMaximizeButton(false);
|
||||||
ptr->addCodeSnippet(1, params.code, params.locationFile, m_activeTokenIds);
|
ptr->setActiveTokenIds(m_activeTokenIds);
|
||||||
|
ptr->setErrorMessages(m_errorMessages);
|
||||||
|
ptr->addCodeSnippet(1, params.code, params.locationFile);
|
||||||
|
|
||||||
ptr->setWindowTitle(FileSystem::fileName(params.locationFile.getFilePath()).c_str());
|
ptr->setWindowTitle(FileSystem::fileName(params.locationFile.getFilePath()).c_str());
|
||||||
ptr->show();
|
ptr->show();
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ public:
|
|||||||
virtual void refreshView();
|
virtual void refreshView();
|
||||||
|
|
||||||
// CodeView implementation
|
// CodeView implementation
|
||||||
virtual void clearCodeSnippets();
|
|
||||||
virtual void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
|
virtual void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
|
||||||
|
virtual void setErrorMessages(const std::vector<std::string>& errorMessages);
|
||||||
|
|
||||||
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
|
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
|
||||||
virtual void showCodeFile(const CodeSnippetParams& params);
|
virtual void showCodeFile(const CodeSnippetParams& params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void doRefreshView();
|
void doRefreshView();
|
||||||
void doClearCodeSnippets();
|
|
||||||
void doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
|
void doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
|
||||||
void doShowCodeFile(const CodeSnippetParams& params);
|
void doShowCodeFile(const CodeSnippetParams& params);
|
||||||
|
|
||||||
@@ -41,13 +41,14 @@ private:
|
|||||||
void clearClosedWindows();
|
void clearClosedWindows();
|
||||||
|
|
||||||
QtThreadedFunctor<> m_refreshViewFunctor;
|
QtThreadedFunctor<> m_refreshViewFunctor;
|
||||||
QtThreadedFunctor<> m_clearCodeSnippetsFunctor;
|
|
||||||
QtThreadedFunctor<const std::vector<CodeSnippetParams>&> m_showCodeSnippetsFunctor;
|
QtThreadedFunctor<const std::vector<CodeSnippetParams>&> m_showCodeSnippetsFunctor;
|
||||||
QtThreadedFunctor<const CodeSnippetParams&> m_showCodeFileFunctor;
|
QtThreadedFunctor<const CodeSnippetParams&> m_showCodeFileFunctor;
|
||||||
|
|
||||||
std::shared_ptr<QtCodeFileList> m_widget;
|
std::shared_ptr<QtCodeFileList> m_widget;
|
||||||
std::vector<std::shared_ptr<QtCodeFileList>> m_windows;
|
std::vector<std::shared_ptr<QtCodeFileList>> m_windows;
|
||||||
|
|
||||||
std::vector<Id> m_activeTokenIds;
|
std::vector<Id> m_activeTokenIds;
|
||||||
|
std::vector<std::string> m_errorMessages;
|
||||||
};
|
};
|
||||||
|
|
||||||
# endif // QT_CODE_VIEW_H
|
# endif // QT_CODE_VIEW_H
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ void Application::loadProject(const std::string& projectSettingsFilePath)
|
|||||||
|
|
||||||
m_project->loadProjectSettings(projectSettingsFilePath);
|
m_project->loadProjectSettings(projectSettingsFilePath);
|
||||||
m_project->parseCode();
|
m_project->parseCode();
|
||||||
|
|
||||||
activateInitialNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadSource(const std::string& sourceDirectoryPath)
|
void Application::loadSource(const std::string& sourceDirectoryPath)
|
||||||
@@ -58,16 +56,12 @@ void Application::loadSource(const std::string& sourceDirectoryPath)
|
|||||||
m_project->clearProjectSettings();
|
m_project->clearProjectSettings();
|
||||||
m_project->setSourceDirectoryPath(sourceDirectoryPath);
|
m_project->setSourceDirectoryPath(sourceDirectoryPath);
|
||||||
m_project->parseCode();
|
m_project->parseCode();
|
||||||
|
|
||||||
activateInitialNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::reloadProject()
|
void Application::reloadProject()
|
||||||
{
|
{
|
||||||
m_project->clearStorage();
|
m_project->clearStorage();
|
||||||
m_project->parseCode();
|
m_project->parseCode();
|
||||||
|
|
||||||
activateInitialNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::saveProject(const std::string& projectSettingsFilePath)
|
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");
|
Id mainId = m_graphAccessProxy->getIdForNodeWithName("main");
|
||||||
|
|
||||||
if (!mainId)
|
if (!mainId)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "component/ComponentManager.h"
|
#include "component/ComponentManager.h"
|
||||||
#include "Project.h"
|
#include "Project.h"
|
||||||
#include "utility/messaging/MessageListener.h"
|
#include "utility/messaging/MessageListener.h"
|
||||||
|
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||||
#include "utility/messaging/type/MessageLoadProject.h"
|
#include "utility/messaging/type/MessageLoadProject.h"
|
||||||
#include "utility/messaging/type/MessageLoadSource.h"
|
#include "utility/messaging/type/MessageLoadSource.h"
|
||||||
#include "utility/messaging/type/MessageRefresh.h"
|
#include "utility/messaging/type/MessageRefresh.h"
|
||||||
@@ -17,7 +18,8 @@ class GraphAccessProxy;
|
|||||||
class LocationAccessProxy;
|
class LocationAccessProxy;
|
||||||
|
|
||||||
class Application
|
class Application
|
||||||
: public MessageListener<MessageLoadProject>
|
: public MessageListener<MessageFinishedParsing>
|
||||||
|
, public MessageListener<MessageLoadProject>
|
||||||
, public MessageListener<MessageLoadSource>
|
, public MessageListener<MessageLoadSource>
|
||||||
, public MessageListener<MessageRefresh>
|
, public MessageListener<MessageRefresh>
|
||||||
, public MessageListener<MessageSaveProject>
|
, public MessageListener<MessageSaveProject>
|
||||||
@@ -35,8 +37,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Application();
|
Application();
|
||||||
|
|
||||||
void activateInitialNode() const;
|
virtual void handleMessage(MessageFinishedParsing* message);
|
||||||
|
|
||||||
virtual void handleMessage(MessageLoadProject* message);
|
virtual void handleMessage(MessageLoadProject* message);
|
||||||
virtual void handleMessage(MessageLoadSource* message);
|
virtual void handleMessage(MessageLoadSource* message);
|
||||||
virtual void handleMessage(MessageRefresh* message);
|
virtual void handleMessage(MessageRefresh* message);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ add_files(
|
|||||||
data/parser/cxx/ASTConsumer.h
|
data/parser/cxx/ASTConsumer.h
|
||||||
data/parser/cxx/ASTVisitor.cpp
|
data/parser/cxx/ASTVisitor.cpp
|
||||||
data/parser/cxx/ASTVisitor.h
|
data/parser/cxx/ASTVisitor.h
|
||||||
|
data/parser/cxx/CxxDiagnosticConsumer.cpp
|
||||||
|
data/parser/cxx/CxxDiagnosticConsumer.h
|
||||||
data/parser/cxx/CxxParser.cpp
|
data/parser/cxx/CxxParser.cpp
|
||||||
data/parser/cxx/CxxParser.h
|
data/parser/cxx/CxxParser.h
|
||||||
data/parser/cxx/utilityCxx.cpp
|
data/parser/cxx/utilityCxx.cpp
|
||||||
|
|||||||
+5
-4
@@ -102,12 +102,13 @@ void Project::parseCode()
|
|||||||
);
|
);
|
||||||
time = clock() - time;
|
time = clock() - time;
|
||||||
|
|
||||||
m_storage->logGraph();
|
// m_storage->logGraph();
|
||||||
m_storage->logLocations();
|
// 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);
|
activeTokenIds = m_graphAccess->getActiveTokenIdsForId(activeTokenIds[0], &declarationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getView()->setActiveTokenIds(activeTokenIds);
|
CodeView* view = getView();
|
||||||
getView()->showCodeSnippets(getSnippetsForActiveTokenIds(activeTokenIds, declarationId));
|
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)
|
void CodeController::handleMessage(MessageRefresh* message)
|
||||||
@@ -78,28 +104,12 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
|||||||
collection.forEachTokenLocationFile(
|
collection.forEachTokenLocationFile(
|
||||||
[&](TokenLocationFile* file) -> void
|
[&](TokenLocationFile* file) -> void
|
||||||
{
|
{
|
||||||
const std::string filePath = file->getFilePath();
|
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
|
||||||
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath);
|
|
||||||
|
|
||||||
std::vector<std::pair<uint, uint>> ranges = getSnippetRangesForFile(file, s_lineRadius);
|
for (CodeView::CodeSnippetParams& params : fileSnippets)
|
||||||
std::vector<CodeView::CodeSnippetParams> fileSnippets;
|
|
||||||
|
|
||||||
for (const std::pair<uint, uint>& range: ranges)
|
|
||||||
{
|
{
|
||||||
unsigned int firstLineNumber = std::max<int>(1, range.first - s_lineRadius);
|
params.locationFile = m_locationAccess->getTokenLocationsForLinesInFile(
|
||||||
unsigned int lastLineNumber = std::min<int>(textAccess->getLineCount(), range.second + s_lineRadius);
|
file->getFilePath(), params.startLineNumber, params.endLineNumber);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declarationId != 0)
|
if (declarationId != 0)
|
||||||
@@ -133,9 +143,32 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
|||||||
return snippets;
|
return snippets;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<uint, uint>> CodeController::getSnippetRangesForFile(
|
std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(const TokenLocationFile* file) const
|
||||||
TokenLocationFile* file, const uint lineRadius
|
{
|
||||||
) 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;
|
std::vector<std::pair<uint, uint>> ranges;
|
||||||
uint start = 0;
|
uint start = 0;
|
||||||
@@ -152,7 +185,7 @@ std::vector<std::pair<uint, uint>> CodeController::getSnippetRangesForFile(
|
|||||||
{
|
{
|
||||||
start = lineNumber;
|
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)));
|
ranges.push_back(std::make_pair(uint(start), uint(end)));
|
||||||
start = lineNumber;
|
start = lineNumber;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "utility/messaging/MessageListener.h"
|
#include "utility/messaging/MessageListener.h"
|
||||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||||
|
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||||
#include "utility/messaging/type/MessageRefresh.h"
|
#include "utility/messaging/type/MessageRefresh.h"
|
||||||
#include "utility/messaging/type/MessageShowFile.h"
|
#include "utility/messaging/type/MessageShowFile.h"
|
||||||
#include "utility/types.h"
|
#include "utility/types.h"
|
||||||
@@ -20,6 +21,7 @@ class CodeController
|
|||||||
: public Controller
|
: public Controller
|
||||||
, public MessageListener<MessageActivateTokenLocation>
|
, public MessageListener<MessageActivateTokenLocation>
|
||||||
, public MessageListener<MessageActivateTokens>
|
, public MessageListener<MessageActivateTokens>
|
||||||
|
, public MessageListener<MessageFinishedParsing>
|
||||||
, public MessageListener<MessageRefresh>
|
, public MessageListener<MessageRefresh>
|
||||||
, public MessageListener<MessageShowFile>
|
, public MessageListener<MessageShowFile>
|
||||||
{
|
{
|
||||||
@@ -32,6 +34,7 @@ private:
|
|||||||
|
|
||||||
virtual void handleMessage(MessageActivateTokenLocation* message);
|
virtual void handleMessage(MessageActivateTokenLocation* message);
|
||||||
virtual void handleMessage(MessageActivateTokens* message);
|
virtual void handleMessage(MessageActivateTokens* message);
|
||||||
|
virtual void handleMessage(MessageFinishedParsing* message);
|
||||||
virtual void handleMessage(MessageRefresh* message);
|
virtual void handleMessage(MessageRefresh* message);
|
||||||
virtual void handleMessage(MessageShowFile* message);
|
virtual void handleMessage(MessageShowFile* message);
|
||||||
|
|
||||||
@@ -39,7 +42,8 @@ private:
|
|||||||
|
|
||||||
std::vector<CodeView::CodeSnippetParams> getSnippetsForActiveTokenIds(
|
std::vector<CodeView::CodeSnippetParams> getSnippetsForActiveTokenIds(
|
||||||
const std::vector<Id>& ids, Id declarationId) const;
|
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;
|
GraphAccess* m_graphAccess;
|
||||||
LocationAccess* m_locationAccess;
|
LocationAccess* m_locationAccess;
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ void GraphController::handleMessage(MessageActivateTokens* message)
|
|||||||
createDummyGraphForTokenIds(m_activeTokenIds);
|
createDummyGraphForTokenIds(m_activeTokenIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphController::handleMessage(MessageFinishedParsing* message)
|
||||||
|
{
|
||||||
|
getView()->clear();
|
||||||
|
}
|
||||||
|
|
||||||
void GraphController::handleMessage(MessageGraphNodeExpand* message)
|
void GraphController::handleMessage(MessageGraphNodeExpand* message)
|
||||||
{
|
{
|
||||||
DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access);
|
DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access);
|
||||||
@@ -153,10 +158,26 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
|
|||||||
|
|
||||||
Edge* edge = child->getMemberEdge();
|
Edge* edge = child->getMemberEdge();
|
||||||
TokenComponentAccess* access = edge->getComponent<TokenComponentAccess>();
|
TokenComponentAccess* access = edge->getComponent<TokenComponentAccess>();
|
||||||
|
TokenComponentAccess::AccessType accessType = TokenComponentAccess::ACCESS_NONE;
|
||||||
|
|
||||||
if (access)
|
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)
|
for (DummyNode& dummy : result.subNodes)
|
||||||
{
|
{
|
||||||
if (dummy.accessType == accessType)
|
if (dummy.accessType == accessType)
|
||||||
@@ -178,10 +199,6 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
parent = &result;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent->subNodes.push_back(createDummyNodeTopDown(child));
|
parent->subNodes.push_back(createDummyNodeTopDown(child));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "utility/messaging/MessageListener.h"
|
#include "utility/messaging/MessageListener.h"
|
||||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||||
|
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||||
#include "utility/messaging/type/MessageGraphNodeExpand.h"
|
#include "utility/messaging/type/MessageGraphNodeExpand.h"
|
||||||
#include "utility/messaging/type/MessageGraphNodeMove.h"
|
#include "utility/messaging/type/MessageGraphNodeMove.h"
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ class Node;
|
|||||||
class GraphController
|
class GraphController
|
||||||
: public Controller
|
: public Controller
|
||||||
, public MessageListener<MessageActivateTokens>
|
, public MessageListener<MessageActivateTokens>
|
||||||
|
, public MessageListener<MessageFinishedParsing>
|
||||||
, public MessageListener<MessageGraphNodeExpand>
|
, public MessageListener<MessageGraphNodeExpand>
|
||||||
, public MessageListener<MessageGraphNodeMove>
|
, public MessageListener<MessageGraphNodeMove>
|
||||||
{
|
{
|
||||||
@@ -47,6 +49,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void handleMessage(MessageActivateTokens* message);
|
virtual void handleMessage(MessageActivateTokens* message);
|
||||||
|
virtual void handleMessage(MessageFinishedParsing* message);
|
||||||
virtual void handleMessage(MessageGraphNodeExpand* message);
|
virtual void handleMessage(MessageGraphNodeExpand* message);
|
||||||
virtual void handleMessage(MessageGraphNodeMove* message);
|
virtual void handleMessage(MessageGraphNodeMove* message);
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ void SearchController::handleMessage(MessageFind* message)
|
|||||||
getView()->setFocus();
|
getView()->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchController::handleMessage(MessageFinishedParsing* message)
|
||||||
|
{
|
||||||
|
getView()->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
void SearchController::handleMessage(MessageRefresh* message)
|
void SearchController::handleMessage(MessageRefresh* message)
|
||||||
{
|
{
|
||||||
getView()->refreshView();
|
getView()->refreshView();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "utility/messaging/MessageListener.h"
|
#include "utility/messaging/MessageListener.h"
|
||||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||||
#include "utility/messaging/type/MessageFind.h"
|
#include "utility/messaging/type/MessageFind.h"
|
||||||
|
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||||
#include "utility/messaging/type/MessageRefresh.h"
|
#include "utility/messaging/type/MessageRefresh.h"
|
||||||
#include "utility/messaging/type/MessageSearch.h"
|
#include "utility/messaging/type/MessageSearch.h"
|
||||||
#include "utility/messaging/type/MessageSearchAutocomplete.h"
|
#include "utility/messaging/type/MessageSearchAutocomplete.h"
|
||||||
@@ -18,6 +19,7 @@ class SearchController
|
|||||||
: public Controller
|
: public Controller
|
||||||
, public MessageListener<MessageActivateTokens>
|
, public MessageListener<MessageActivateTokens>
|
||||||
, public MessageListener<MessageFind>
|
, public MessageListener<MessageFind>
|
||||||
|
, public MessageListener<MessageFinishedParsing>
|
||||||
, public MessageListener<MessageRefresh>
|
, public MessageListener<MessageRefresh>
|
||||||
, public MessageListener<MessageSearch>
|
, public MessageListener<MessageSearch>
|
||||||
, public MessageListener<MessageSearchAutocomplete>
|
, public MessageListener<MessageSearchAutocomplete>
|
||||||
@@ -29,6 +31,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
virtual void handleMessage(MessageActivateTokens* message);
|
virtual void handleMessage(MessageActivateTokens* message);
|
||||||
virtual void handleMessage(MessageFind* message);
|
virtual void handleMessage(MessageFind* message);
|
||||||
|
virtual void handleMessage(MessageFinishedParsing* message);
|
||||||
virtual void handleMessage(MessageRefresh* message);
|
virtual void handleMessage(MessageRefresh* message);
|
||||||
virtual void handleMessage(MessageSearch* message);
|
virtual void handleMessage(MessageSearch* message);
|
||||||
virtual void handleMessage(MessageSearchAutocomplete* message);
|
virtual void handleMessage(MessageSearchAutocomplete* message);
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include "component/view/StatusBarView.h"
|
#include "component/view/StatusBarView.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
StatusBarController::StatusBarController()
|
StatusBarController::StatusBarController()
|
||||||
: MessageListener<MessageError>(true)
|
: MessageListener<MessageError>(true)
|
||||||
, MessageListener<MessageFinishedParsing>(true)
|
, MessageListener<MessageFinishedParsing>(true)
|
||||||
@@ -23,7 +26,14 @@ StatusBarView* StatusBarController::getView()
|
|||||||
|
|
||||||
void StatusBarController::handleMessage(MessageFinishedParsing* message)
|
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)
|
void StatusBarController::handleMessage(MessageStatus* message)
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ public:
|
|||||||
|
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
|
|
||||||
virtual void clearCodeSnippets() = 0;
|
|
||||||
virtual void setActiveTokenIds(const std::vector<Id>& activeTokenIds) = 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 showCodeSnippets(const std::vector<CodeSnippetParams>& snippets) = 0;
|
||||||
virtual void showCodeFile(const CodeSnippetParams& params) = 0;
|
virtual void showCodeFile(const CodeSnippetParams& params) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,30 @@ void Storage::logLocations() const
|
|||||||
LOG_INFO_STREAM(<< '\n' << m_locationCollection);
|
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(
|
Id Storage::onTypedefParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseTypeUsage& underlyingType,
|
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());
|
ret.push_back(token->getId());
|
||||||
|
|
||||||
Node* node;
|
|
||||||
if (token->isNode())
|
if (token->isNode())
|
||||||
{
|
{
|
||||||
Node* node = dynamic_cast<Node*>(token);
|
Node* node = dynamic_cast<Node*>(token);
|
||||||
@@ -744,6 +767,13 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile(
|
|||||||
return ret;
|
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
|
const Graph& Storage::getGraph() const
|
||||||
{
|
{
|
||||||
return m_graph;
|
return m_graph;
|
||||||
@@ -941,8 +971,16 @@ bool Storage::getSubQuerySearchResults(
|
|||||||
{
|
{
|
||||||
if (word.size())
|
if (word.size())
|
||||||
{
|
{
|
||||||
SearchResults res = node->runFuzzySearch(word);
|
if (searchNodes.size() > 1)
|
||||||
results->insert(res.begin(), res.end());
|
{
|
||||||
|
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)
|
else if (searchNodes.size() == 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ public:
|
|||||||
void logGraph() const;
|
void logGraph() const;
|
||||||
void logLocations() const;
|
void logLocations() const;
|
||||||
|
|
||||||
|
size_t getErrorCount() const;
|
||||||
|
|
||||||
// ParserClient implementation
|
// ParserClient implementation
|
||||||
|
virtual void onError(const ParseLocation& location, const std::string& message);
|
||||||
|
|
||||||
virtual Id onTypedefParsed(
|
virtual Id onTypedefParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
||||||
const ParseTypeUsage& underlyingType, AccessType access);
|
const ParseTypeUsage& underlyingType, AccessType access);
|
||||||
@@ -108,6 +112,8 @@ public:
|
|||||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const Graph& getGraph() const;
|
const Graph& getGraph() const;
|
||||||
const TokenLocationCollection& getTokenLocationCollection() const;
|
const TokenLocationCollection& getTokenLocationCollection() const;
|
||||||
@@ -137,6 +143,9 @@ private:
|
|||||||
|
|
||||||
SearchIndex m_tokenIndex;
|
SearchIndex m_tokenIndex;
|
||||||
SearchIndex m_filterIndex;
|
SearchIndex m_filterIndex;
|
||||||
|
|
||||||
|
TokenLocationCollection m_errorLocationCollection;
|
||||||
|
std::vector<std::string> m_errorMessages;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STORAGE_H
|
#endif // STORAGE_H
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public:
|
|||||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||||
) const = 0;
|
) const = 0;
|
||||||
|
|
||||||
|
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,3 +60,13 @@ TokenLocationFile LocationAccessProxy::getTokenLocationsForLinesInFile(
|
|||||||
|
|
||||||
return TokenLocationFile("");
|
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 std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LocationAccess* m_subject;
|
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(
|
ParseLocation::ParseLocation(
|
||||||
const std::string& filePath,
|
const std::string& filePath,
|
||||||
uint startLineNumber, uint startColumnNumber,
|
uint startLineNumber, uint startColumnNumber,
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
struct ParseLocation
|
struct ParseLocation
|
||||||
{
|
{
|
||||||
ParseLocation();
|
ParseLocation();
|
||||||
|
ParseLocation(
|
||||||
|
const std::string& filePath,
|
||||||
|
uint lineNumber,
|
||||||
|
uint columnNumber
|
||||||
|
);
|
||||||
ParseLocation(
|
ParseLocation(
|
||||||
const std::string& filePath,
|
const std::string& filePath,
|
||||||
uint startLineNumber, uint startColumnNumber,
|
uint startLineNumber, uint startColumnNumber,
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ public:
|
|||||||
ParserClient();
|
ParserClient();
|
||||||
virtual ~ParserClient();
|
virtual ~ParserClient();
|
||||||
|
|
||||||
|
virtual void onError(const ParseLocation& location, const std::string& message) = 0;
|
||||||
|
|
||||||
virtual Id onTypedefParsed(
|
virtual Id onTypedefParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
const ParseLocation& location, const std::vector<std::string>& nameHierarchy,
|
||||||
const ParseTypeUsage& underlyingType, AccessType access) = 0;
|
const ParseTypeUsage& underlyingType, AccessType access) = 0;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "data/parser/cxx/ASTConsumer.h"
|
#include "data/parser/cxx/ASTConsumer.h"
|
||||||
|
|
||||||
|
#include "data/parser/ParserClient.h"
|
||||||
|
|
||||||
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client)
|
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client)
|
||||||
: m_visitor(context, 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/CxxParser.h"
|
||||||
|
|
||||||
#include "data/parser/cxx/ASTActionFactory.h"
|
|
||||||
#include "utility/logging/logging.h"
|
#include "utility/logging/logging.h"
|
||||||
#include "utility/text/TextAccess.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)
|
CxxParser::CxxParser(ParserClient* client)
|
||||||
: Parser(client)
|
: Parser(client)
|
||||||
{
|
{
|
||||||
@@ -68,15 +113,22 @@ void CxxParser::parseFiles(
|
|||||||
|
|
||||||
clang::tooling::ClangTool tool(*compilationDatabase, filePaths);
|
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);
|
tool.run(&actionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CxxParser::parseFile(std::shared_ptr<TextAccess> textAccess)
|
void CxxParser::parseFile(std::shared_ptr<TextAccess> textAccess)
|
||||||
{
|
{
|
||||||
ASTActionFactory actionFactory(m_client);
|
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
args.push_back("-fno-delayed-template-parsing");
|
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;
|
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
|
void SearchNode::addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const
|
||||||
{
|
{
|
||||||
result.insert(SearchResult(weight, node, this));
|
result.insert(SearchResult(weight, node, this));
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
const std::set<std::shared_ptr<SearchNode>>& getChildren() const;
|
const std::set<std::shared_ptr<SearchNode>>& getChildren() const;
|
||||||
|
|
||||||
SearchResults runFuzzySearch(const std::string& query) 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;
|
void addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
class MessageFinishedParsing: public Message<MessageFinishedParsing>
|
class MessageFinishedParsing: public Message<MessageFinishedParsing>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MessageFinishedParsing()
|
MessageFinishedParsing(float parseTime, size_t errorCount)
|
||||||
|
: parseTime(parseTime)
|
||||||
|
, errorCount(errorCount)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,6 +16,9 @@ public:
|
|||||||
{
|
{
|
||||||
return "MessageFinishedParsing";
|
return "MessageFinishedParsing";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float parseTime;
|
||||||
|
size_t errorCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESSAGE_FINISHED_PARSING_H
|
#endif // MESSAGE_FINISHED_PARSING_H
|
||||||
|
|||||||
@@ -1397,6 +1397,8 @@ public:
|
|||||||
filePaths.push_back("data/CxxParserTestSuite/code.cpp");
|
filePaths.push_back("data/CxxParserTestSuite/code.cpp");
|
||||||
parser.parseFiles(filePaths, std::vector<std::string>(), std::vector<std::string>());
|
parser.parseFiles(filePaths, std::vector<std::string>(), std::vector<std::string>());
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(client.errors.size(), 0);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(client.typedefs.size(), 1);
|
TS_ASSERT_EQUALS(client.typedefs.size(), 1);
|
||||||
TS_ASSERT_EQUALS(client.classes.size(), 4);
|
TS_ASSERT_EQUALS(client.classes.size(), 4);
|
||||||
TS_ASSERT_EQUALS(client.enums.size(), 1);
|
TS_ASSERT_EQUALS(client.enums.size(), 1);
|
||||||
@@ -1414,10 +1416,25 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client.typeUses.size(), 8);
|
TS_ASSERT_EQUALS(client.typeUses.size(), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_catches_error()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"int a = b;\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(client->errors.size(), 1);
|
||||||
|
TS_ASSERT_EQUALS(client->errors[0], "use of undeclared identifier \'b\' <1:9 1:9>");
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class TestParserClient: public ParserClient
|
class TestParserClient: public ParserClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual void onError(const ParseLocation& location, const std::string& message)
|
||||||
|
{
|
||||||
|
errors.push_back(addLocationSuffix(message, location));
|
||||||
|
}
|
||||||
|
|
||||||
virtual Id onTypedefParsed(
|
virtual Id onTypedefParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseTypeUsage& underlyingType,
|
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseTypeUsage& underlyingType,
|
||||||
AccessType access
|
AccessType access
|
||||||
@@ -1610,6 +1627,8 @@ private:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> errors;
|
||||||
|
|
||||||
std::vector<std::string> typedefs;
|
std::vector<std::string> typedefs;
|
||||||
std::vector<std::string> classes;
|
std::vector<std::string> classes;
|
||||||
std::vector<std::string> enums;
|
std::vector<std::string> enums;
|
||||||
|
|||||||
Reference in New Issue
Block a user