* work save: compile issue panel

This commit is contained in:
royqh1979@gmail.com 2021-06-23 22:38:02 +08:00
parent aad78fa475
commit 92ffbb084f
11 changed files with 398 additions and 9 deletions

View File

@ -10,6 +10,8 @@ CompilerManager::CompilerManager(QObject *parent) : QObject(parent)
mCompiler = nullptr;
mBackgroundSyntaxChecker = nullptr;
mRunner = nullptr;
mSyntaxCheckErrorCount = 0;
mCompileErrorCount = 0;
}
bool CompilerManager::compiling()
@ -28,8 +30,10 @@ void CompilerManager::compile(const QString& filename, const QByteArray& encodin
if (mCompiler!=nullptr) {
return;
}
mCompileErrorCount = 0;
mCompiler = new FileCompiler(filename,encoding,silent,onlyCheckSyntax);
connect(mCompiler, &Compiler::compileFinished, this ,&CompilerManager::onCompileFinished);
connect(mCompiler, &Compiler::compileFinished, pMainWindow, &MainWindow::onCompileFinished);
connect(mCompiler, &Compiler::compileOutput, pMainWindow, &MainWindow::onCompileLog);
connect(mCompiler, &Compiler::compileIssue, pMainWindow, &MainWindow::onCompileIssue);
connect(mCompiler, &Compiler::compileErrorOccured, pMainWindow, &MainWindow::onCompileErrorOccured);
@ -60,7 +64,6 @@ bool CompilerManager::canCompile(const QString &filename)
void CompilerManager::onCompileFinished()
{
QMutexLocker locker(&compileMutex);
qDebug() << "Compile finished";
mCompiler=nullptr;
delete mCompiler;
}
@ -72,6 +75,16 @@ void CompilerManager::onRunnerTerminated()
mRunner=nullptr;
}
int CompilerManager::syntaxCheckErrorCount() const
{
return mSyntaxCheckErrorCount;
}
int CompilerManager::compileErrorCount() const
{
return mCompileErrorCount;
}
CompileError::CompileError(const QString &reason):BaseError(reason)
{

View File

@ -19,11 +19,17 @@ public:
void compile(const QString& filename, const QByteArray& encoding, bool silent=false,bool onlyCheckSyntax=false);
void run(const QString& filename, const QString& arguments, const QString& workDir);
bool canCompile(const QString& filename);
int compileErrorCount() const;
int syntaxCheckErrorCount() const;
private slots:
void onCompileFinished();
void onRunnerTerminated();
private:
Compiler* mCompiler;
int mCompileErrorCount;
int mSyntaxCheckErrorCount;
Compiler* mBackgroundSyntaxChecker;
ExecutableRunner* mRunner;
QMutex compileMutex;

View File

@ -409,6 +409,115 @@ void Editor::copyAsHTML()
QGuiApplication::clipboard()->setMimeData(mimeData);
}
void Editor::addSyntaxIssues(int line, int startChar, CompileIssueType errorType, const QString &hint)
{
PSyntaxIssue pError;
BufferCoord p;
QString token;
SynHighlighterTokenType tokenType;
int tokenKind,start;
PSynHighlighterAttribute attr;
PSyntaxIssueList lst;
if ((line<1) || (line>lines()->count()))
return;
pError = std::make_shared<SyntaxIssue>();
p.Char = startChar;
p.Line = line;
if (startChar >= lines()->getString(line-1).length()) {
start = 1;
token = lines()->getString(line-1);
} else {
if (!GetHighlighterAttriAtRowColEx(p,token,tokenType,tokenKind,start,attr))
return;
}
pError->startChar = start;
pError->endChar = start + token.length();
pError->col = charToColumn(line,pError->startChar);
pError->endCol = charToColumn(line,pError->endChar);
pError->hint = hint;
pError->token = token;
pError->issueType = errorType;
if (mSyntaxIssues.contains(line)) {
lst = mSyntaxIssues[line];
} else {
lst = std::make_shared<SyntaxIssueList>();
mSyntaxIssues[line] = lst;
}
lst->append(pError);
}
void Editor::clearSyntaxIssues()
{
mSyntaxIssues.clear();
}
void Editor::gotoNextSyntaxIssue()
{
auto iter = mSyntaxIssues.find(caretY());
if (iter==mSyntaxIssues.end())
return;
iter++;
if (iter==mSyntaxIssues.end())
return;
BufferCoord p;
p.Char = (*iter)->at(0)->startChar;
p.Line = iter.key();
setCaretXY(p);
}
void Editor::gotoPrevSyntaxIssue()
{
auto iter = mSyntaxIssues.find(caretY());
if (iter==mSyntaxIssues.end())
return;
if (iter==mSyntaxIssues.begin())
return;
iter--;
BufferCoord p;
p.Char = (*iter)->at(0)->startChar;
p.Line = iter.key();
setCaretXY(p);
}
bool Editor::hasNextSyntaxIssue() const
{
auto iter = mSyntaxIssues.find(caretY());
if (iter==mSyntaxIssues.end())
return false;
iter++;
if (iter==mSyntaxIssues.end())
return false;
return true;
}
bool Editor::hasPrevSyntaxIssue() const
{
auto iter = mSyntaxIssues.find(caretY());
if (iter==mSyntaxIssues.end())
return true;
if (iter==mSyntaxIssues.begin())
return true;
return false;
}
Editor::PSyntaxIssueList Editor::getErrorsAtLine(int line)
{
if (mSyntaxIssues.contains(line))
return mSyntaxIssues[line];
return PSyntaxIssueList();
}
Editor::PSyntaxIssue Editor::getErrorAtPosition(const BufferCoord &pos)
{
PSyntaxIssueList lst = getErrorsAtLine(pos.Line);
for (PSyntaxIssue issue: *lst) {
if (issue->startChar<=pos.Char && pos.Char<=issue->endChar)
return issue;
}
return PSyntaxIssue();
}
void Editor::onModificationChanged(bool) {
updateCaption();
}

View File

@ -6,6 +6,7 @@
#include <QTabWidget>
#include "qsynedit/SynEdit.h"
#include "colorscheme.h"
#include "common.h"
class SaveException: public std::exception {
@ -46,6 +47,20 @@ public:
RawStringNoEscape
};
struct SyntaxIssue {
int col;
int endCol;
int startChar;
int endChar;
CompileIssueType issueType;
QString token;
QString hint;
};
using PSyntaxIssue = std::shared_ptr<SyntaxIssue>;
using SyntaxIssueList = QVector<PSyntaxIssue>;
using PSyntaxIssueList = std::shared_ptr<SyntaxIssueList>;
explicit Editor(QWidget *parent);
explicit Editor(QWidget *parent, const QString& filename,
@ -82,6 +97,15 @@ public:
void copyToClipboard() override;
void cutToClipboard() override;
void copyAsHTML();
void addSyntaxIssues(int line, int startChar, CompileIssueType errorType, const QString& hint);
void clearSyntaxIssues();
void gotoNextSyntaxIssue();
void gotoPrevSyntaxIssue();
bool hasPrevSyntaxIssue() const;
bool hasNextSyntaxIssue() const;
PSyntaxIssueList getErrorsAtLine(int line);
PSyntaxIssue getErrorAtPosition(const BufferCoord& pos);
signals:
@ -114,6 +138,7 @@ private:
QTabWidget* mParentPageControl;
bool mInProject;
bool mIsNew;
QMap<int,PSyntaxIssueList> mSyntaxIssues;
// QWidget interface
protected:

View File

@ -5,6 +5,7 @@
#include <mainwindow.h>
#include <iconv.h>
#include <QDebug>
#include <QFileInfo>
EditorList::EditorList(QTabWidget* leftPageWidget,
QTabWidget* rightPageWidget,
@ -128,6 +129,23 @@ void EditorList::applyColorSchemes(const QString& name)
}
}
bool EditorList::isFileOpened(const QString &name)
{
QFileInfo fileInfo(name);
QString filename = fileInfo.absoluteFilePath();
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
if (e->filename().compare(filename)==0)
return true;
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
if (e->filename().compare(filename)==0)
return true;
}
return false;
}
bool EditorList::closeAll(bool force) {
beginUpdate();
auto end = finally([this] {

View File

@ -40,6 +40,7 @@ public:
void endUpdate();
void applySettings();
void applyColorSchemes(const QString& name);
bool isFileOpened(const QString& name);
private:
QTabWidget* getNewEditorPageControl() const;

View File

@ -22,8 +22,10 @@
MainWindow* pMainWindow;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
: QMainWindow(parent),
ui(new Ui::MainWindow),
mMessageControlChanged(false),
mCheckSyntaxInBack(false)
{
ui->setupUi(this);
// status bar
@ -71,8 +73,9 @@ MainWindow::MainWindow(QWidget *parent)
ui->actionEncode_in_ANSI->setCheckable(true);
ui->actionEncode_in_UTF_8->setCheckable(true);
openCloseMessageSheet(false);
mPreviousHeight = 250;
updateEditorActions();
applySettings();
}
@ -249,6 +252,36 @@ void MainWindow::updateCompilerSet()
mCompilerSet->setCurrentIndex(index);
}
void MainWindow::openCloseMessageSheet(bool open)
{
// if Assigned(fReportToolWindow) then
// Exit;
// Switch between open and close
if (open) {
QList<int> sizes = ui->splitterMessages->sizes();
int tabHeight = ui->tabMessages->tabBar()->height();
ui->tabMessages->setMinimumHeight(tabHeight+5);
int totalSize = sizes[0] + sizes[1];
sizes[1] = mPreviousHeight;
sizes[0] = std::max(1,totalSize - sizes[1]);
ui->splitterMessages->setSizes(sizes);
} else {
QList<int> sizes = ui->splitterMessages->sizes();
mPreviousHeight = sizes[1];
int totalSize = sizes[0] + sizes[1];
int tabHeight = ui->tabMessages->tabBar()->height();
ui->tabMessages->setMinimumHeight(tabHeight);
sizes[1] = tabHeight;
sizes[0] = std::max(1,totalSize - sizes[1]);
ui->splitterMessages->setSizes(sizes);
}
QSplitterHandle* handle = ui->splitterMessages->handle(1);
handle->setEnabled(open);
int idxClose = ui->tabMessages->indexOf(ui->tabClose);
ui->tabMessages->setTabVisible(idxClose,open);
}
void MainWindow::on_actionNew_triggered()
{
@ -337,6 +370,104 @@ void MainWindow::onCompileLog(const QString &msg)
void MainWindow::onCompileIssue(PCompileIssue issue)
{
ui->tableIssues->addIssue(issue);
// Update tab caption
// if CompilerOutput.Items.Count = 1 then
// CompSheet.Caption := Lang[ID_SHEET_COMP] + ' (' + IntToStr(CompilerOutput.Items.Count) + ')';
if (issue->type == CompileIssueType::Error || issue->type ==
CompileIssueType::Warning) {
Editor* e = mEditorList->getOpenedEditorByFilename(issue->filename);
if (e!=nullptr && (issue->line>0)) {
int line = issue->line;
if (line > e->lines()->count())
return;
int col = std::min(issue->column,e->lines()->getString(line-1).length()+1);
e->addSyntaxIssues(line,col,issue->type,issue->description);
}
}
}
void MainWindow::onCompileFinished()
{
// Update tab caption
int i = ui->tabMessages->indexOf(ui->tabIssues);
if (i==-1)
return;
ui->tabMessages->setTabText(i, tr("Issues") +
QString(" (%1)").arg(ui->tableIssues->model()->rowCount()));
// Close it if there's nothing to show
if (mCheckSyntaxInBack) {
// check syntax in back, don't change message panel
} else if (
(ui->tableIssues->count() == 0)
// and (ResourceOutput.Items.Count = 0)
// and devData.AutoCloseProgress
) {
openCloseMessageSheet(false);
// Or open it if there is anything to show
} else {
if (ui->tableIssues->count() > 0) {
if (ui->tabMessages->currentIndex() != i) {
ui->tabMessages->setCurrentIndex(i);
mMessageControlChanged = false;
}
// end else if (ResourceOutput.Items.Count > 0) then begin
// if MessageControl.ActivePage <> ResSheet then begin
// MessageControl.ActivePage := ResSheet;
// fMessageControlChanged := False;
// end;
// end;
openCloseMessageSheet(true);
}
}
Editor * e = mEditorList->getEditor();
if (e!=nullptr) {
e->beginUpdate();
e->endUpdate();
}
// Jump to problem location, sorted by significance
if ((mCompilerManager->compileErrorCount() > 0) && (!mCheckSyntaxInBack)) {
// First try to find errors
for (int i=0;i<ui->tableIssues->count();i++) {
PCompileIssue issue = ui->tableIssues->issue(i);
if (issue->type == CompileIssueType::Error) {
ui->tableIssues->selectRow(i);
QModelIndex index =ui->tableIssues->model()->index(i,0);
ui->tableIssues->doubleClicked(index);
}
}
// Then try to find warnings
for (int i=0;i<ui->tableIssues->count();i++) {
PCompileIssue issue = ui->tableIssues->issue(i);
if (issue->type == CompileIssueType::Warning) {
ui->tableIssues->selectRow(i);
QModelIndex index =ui->tableIssues->model()->index(i,0);
ui->tableIssues->doubleClicked(index);
}
}
// Then try to find anything with a line number...
// for I := 0 to CompilerOutput.Items.Count - 1 do begin
// if not SameStr(CompilerOutput.Items[I].Caption, '') then begin
// CompilerOutput.Selected := CompilerOutput.Items[I];
// CompilerOutput.Selected.MakeVisible(False);
// CompilerOutputDblClick(CompilerOutput);
// Exit;
// end;
// end;
// Then try to find a resource error
// if ResourceOutput.Items.Count > 0 then begin
// ResourceOutput.Selected := ResourceOutput.Items[0];
// ResourceOutput.Selected.MakeVisible(False);
// CompilerOutputDblClick(ResourceOutput);
// end;
}
mCheckSyntaxInBack=false;
}
void MainWindow::onCompileErrorOccured(const QString &reason)
@ -523,3 +654,14 @@ void MainWindow::on_actionConvert_to_UTF_8_triggered()
return;
editor->convertToEncoding(ENCODING_UTF8);
}
void MainWindow::on_tabMessages_tabBarClicked(int index)
{
mMessageControlChanged = false;
int idxClose = ui->tabMessages->indexOf(ui->tabClose);
if (index == idxClose) {
openCloseMessageSheet(false);
} else {
openCloseMessageSheet(true);
}
}

View File

@ -88,15 +88,19 @@ private slots:
void on_actionConvert_to_UTF_8_triggered();
void on_tabMessages_tabBarClicked(int index);
public slots:
void onCompileLog(const QString& msg);
void onCompileIssue(PCompileIssue issue);
void onCompileFinished();
void onCompileErrorOccured(const QString& reason);
private:
void setupActions();
void updateCompilerSet();
void openCloseMessageSheet(bool open);
private:
Ui::MainWindow *ui;
@ -108,6 +112,9 @@ private:
QMenu * mMenuEncodingList;
QComboBox* mCompilerSet;
CompilerManager* mCompilerManager;
bool mMessageControlChanged;
bool mCheckSyntaxInBack;
int mPreviousHeight;
// QWidget interface
protected:

View File

@ -33,10 +33,13 @@
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<widget class="QSplitter" name="splitterMessages">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -58,11 +61,14 @@
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter_2">
<widget class="QSplitter" name="splitterInfos">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTabWidget" name="tabWidget_2">
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QTabWidget" name="tabInfos">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>1</horstretch>
@ -147,7 +153,7 @@
</item>
</layout>
</widget>
<widget class="QTabWidget" name="tabWidget">
<widget class="QTabWidget" name="tabMessages">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -158,9 +164,14 @@
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>0</number>
<number>5</number>
</property>
<widget class="QWidget" name="tabIssues">
<attribute name="icon">
<iconset>
<normalon>:/icons/images/newlook24/013-compile.png</normalon>
</iconset>
</attribute>
<attribute name="title">
<string>Issues</string>
</attribute>
@ -204,7 +215,22 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabResource">
<attribute name="icon">
<iconset>
<normalon>:/icons/images/newlook24/068-resrc.png</normalon>
</iconset>
</attribute>
<attribute name="title">
<string>Resource</string>
</attribute>
</widget>
<widget class="QWidget" name="tabCompilerOutput">
<attribute name="icon">
<iconset>
<normalon>:/icons/images/newlook24/015-compres.png</normalon>
</iconset>
</attribute>
<attribute name="title">
<string>Compile Log</string>
</attribute>
@ -239,6 +265,36 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDebug">
<attribute name="icon">
<iconset>
<normalon>:/icons/images/newlook24/020-debug.png</normalon>
</iconset>
</attribute>
<attribute name="title">
<string>Debug</string>
</attribute>
</widget>
<widget class="QWidget" name="tabSearch">
<attribute name="icon">
<iconset>
<normalon>:/icons/images/newlook24/074-search.png</normalon>
</iconset>
</attribute>
<attribute name="title">
<string>Search</string>
</attribute>
</widget>
<widget class="QWidget" name="tabClose">
<attribute name="icon">
<iconset>
<normalon>:/icons/images/newlook24/008-close.png</normalon>
</iconset>
</attribute>
<attribute name="title">
<string>Close</string>
</attribute>
</widget>
</widget>
</widget>
</item>

View File

@ -69,6 +69,11 @@ PCompileIssue IssuesModel::issue(int row)
return mIssues[row];
}
int IssuesModel::count()
{
return mIssues.size();
}
void IssuesTable::addIssue(PCompileIssue issue)
{
mModel->addIssue(issue);
@ -84,6 +89,11 @@ PCompileIssue IssuesTable::issue(const int row)
return mModel->issue(row);
}
int IssuesTable::count()
{
return mModel->count();
}
void IssuesTable::clearIssues()
{
mModel->clearIssues();

View File

@ -26,6 +26,7 @@ private:
// QAbstractItemModel interface
public:
int count();
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
@ -51,6 +52,7 @@ public slots:
PCompileIssue issue(const QModelIndex& index);
PCompileIssue issue(const int row);
int count();
void clearIssues();