* work save: back ground syntax check

This commit is contained in:
royqh1979 2021-06-24 20:43:09 +08:00
parent 1f403198e5
commit a4da674e03
18 changed files with 237 additions and 36 deletions

View File

@ -34,6 +34,8 @@ PSynHighlighter HighlighterManager::copyHighlighter(PSynHighlighter highlighter)
return PSynHighlighter();
if (highlighter->getName() == SYN_HIGHLIGHTER_CPP)
return getCppHighlighter();
//todo
return PSynHighlighter();
}
PSynHighlighter HighlighterManager::getCppHighlighter()

View File

@ -15,6 +15,7 @@ SOURCES += \
compiler/compilermanager.cpp \
compiler/executablerunner.cpp \
compiler/filecompiler.cpp \
compiler/stdincompiler.cpp \
editor.cpp \
editorlist.cpp \
iconsmanager.cpp \
@ -58,6 +59,7 @@ HEADERS += \
compiler/compilermanager.h \
compiler/executablerunner.h \
compiler/filecompiler.h \
compiler/stdincompiler.h \
editor.h \
editorlist.h \
iconsmanager.h \

View File

@ -9,10 +9,13 @@
#include <QDebug>
#include <QTime>
Compiler::Compiler(bool silent,bool onlyCheckSyntax):
#define COMPILE_PROCESS_END "---//END//----"
Compiler::Compiler(const QString &filename, bool silent, bool onlyCheckSyntax):
QThread(),
mSilent(silent),
mOnlyCheckSyntax(onlyCheckSyntax)
mOnlyCheckSyntax(onlyCheckSyntax),
mFilename(filename)
{
}
@ -26,8 +29,7 @@ void Compiler::run()
mWarningCount = 0;
QElapsedTimer timer;
timer.start();
runCommand(mCompiler, mArguments, QFileInfo(mCompiler).absolutePath());
runCommand(mCompiler, mArguments, QFileInfo(mCompiler).absolutePath(), pipedText());
log("");
log(tr("Compile Result:"));
log("------------------");
@ -62,9 +64,10 @@ QString Compiler::getFileNameFromOutputLine(QString &line) {
temp = line.mid(0,pos);
line.remove(0,pos+1);
line=line.trimmed();
// if (temp.compare("<stdin>", Qt::CaseInsensitive)!=0 && !QFile(temp).exists()) {
// continue;
// }
if (temp.compare("<stdin>", Qt::CaseInsensitive)==0 ) {
temp = mFilename;
break;
}
if (QFileInfo(temp).fileName() == QLatin1String("ld.exe")) { // skip ld.exe
continue;
@ -137,6 +140,13 @@ CompileIssueType Compiler::getIssueTypeFromOutputLine(QString &line)
void Compiler::processOutput(QString &line)
{
if (line == COMPILE_PROCESS_END) {
if (mLastIssue) {
emit compileIssue(mLastIssue);
mLastIssue.reset();
}
return;
}
QString inFilePrefix = QString("In file included from ");
QString fromPrefix = QString("from ");
PCompileIssue issue = std::make_shared<CompileIssue>();
@ -362,11 +372,14 @@ void Compiler::runCommand(const QString &cmd, const QString &arguments, const Q
process.connect(&process, &QProcess::readyReadStandardOutput,[&process,this](){
this->log(QString::fromLocal8Bit( process.readAllStandardOutput()));
});
process.connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),[&process,this](){
this->error(COMPILE_PROCESS_END);
});
process.start();
if (!inputText.isEmpty())
process.write(inputText.toUtf8());
process.closeWriteChannel();
process.waitForStarted(5000);
if (!inputText.isEmpty())
process.write(inputText.toLocal8Bit());
process.closeWriteChannel();
while (true) {
process.waitForFinished(1000);
if (process.state()!=QProcess::Running) {
@ -407,6 +420,7 @@ void Compiler::log(const QString &msg)
void Compiler::error(const QString &msg)
{
if (msg != COMPILE_PROCESS_END)
emit compileOutput(msg);
for (QString& s:msg.split("\n")) {
if (!s.isEmpty())

View File

@ -16,7 +16,7 @@ public:
Project,
StdIn
};
Compiler(bool silent,bool onlyCheckSyntax);
Compiler(const QString& filename, bool silent,bool onlyCheckSyntax);
signals:
void compileStarted();
@ -38,6 +38,7 @@ protected:
protected:
virtual Settings::PCompilerSet compilerSet() = 0;
virtual bool prepareForCompile() = 0;
virtual QString pipedText() = 0;
virtual QString getCharsetArgument(const QByteArray& encoding);
virtual QString getCCompileArguments(bool checkSyntax);
virtual QString getCppCompileArguments(bool checkSyntax);
@ -57,6 +58,7 @@ protected:
int mErrorCount;
int mWarningCount;
PCompileIssue mLastIssue;
QString mFilename;
private:
bool mStop;

View File

@ -1,5 +1,6 @@
#include "compilermanager.h"
#include "filecompiler.h"
#include "stdincompiler.h"
#include <QDebug>
#include "../mainwindow.h"
#include "executablerunner.h"
@ -41,6 +42,23 @@ void CompilerManager::compile(const QString& filename, const QByteArray& encodin
mCompiler->start();
}
void CompilerManager::checkSyntax(const QString &filename, const QString &content)
{
QMutexLocker locker(&backgroundSyntaxChekMutex);
if (mBackgroundSyntaxChecker!=nullptr) {
return;
}
mSyntaxCheckErrorCount = 0;
mBackgroundSyntaxChecker = new StdinCompiler(filename,content,true,true);
connect(mBackgroundSyntaxChecker, &Compiler::compileFinished, this ,&CompilerManager::onSyntaxCheckFinished);
connect(mBackgroundSyntaxChecker, &Compiler::compileIssue, this, &CompilerManager::onSyntaxCheckIssue);
connect(mBackgroundSyntaxChecker, &Compiler::compileFinished, pMainWindow, &MainWindow::onCompileFinished);
connect(mBackgroundSyntaxChecker, &Compiler::compileOutput, pMainWindow, &MainWindow::onCompileLog);
connect(mBackgroundSyntaxChecker, &Compiler::compileIssue, pMainWindow, &MainWindow::onCompileIssue);
connect(mBackgroundSyntaxChecker, &Compiler::compileErrorOccured, pMainWindow, &MainWindow::onCompileErrorOccured);
mBackgroundSyntaxChecker->start();
}
void CompilerManager::run(const QString &filename, const QString &arguments, const QString &workDir)
{
QMutexLocker locker(&runnerMutex);
@ -81,6 +99,18 @@ void CompilerManager::onCompileIssue(PCompileIssue)
mCompileErrorCount ++;
}
void CompilerManager::onSyntaxCheckFinished()
{
QMutexLocker locker(&backgroundSyntaxChekMutex);
delete mBackgroundSyntaxChecker;
mBackgroundSyntaxChecker=nullptr;
}
void CompilerManager::onSyntaxCheckIssue(PCompileIssue)
{
mSyntaxCheckErrorCount++;
}
int CompilerManager::syntaxCheckErrorCount() const
{
return mSyntaxCheckErrorCount;

View File

@ -18,6 +18,7 @@ public:
bool backgroundSyntaxChecking();
void compile(const QString& filename, const QByteArray& encoding, bool silent=false,bool onlyCheckSyntax=false);
void checkSyntax(const QString&filename, const QString& content);
void run(const QString& filename, const QString& arguments, const QString& workDir);
bool canCompile(const QString& filename);
int compileErrorCount() const;
@ -25,9 +26,11 @@ public:
int syntaxCheckErrorCount() const;
private slots:
void onCompileFinished();
void onRunnerTerminated();
void onCompileFinished();
void onCompileIssue(PCompileIssue issue);
void onSyntaxCheckFinished();
void onSyntaxCheckIssue(PCompileIssue issue);
private:
Compiler* mCompiler;

View File

@ -9,8 +9,7 @@
FileCompiler::FileCompiler(const QString &filename, const QByteArray &encoding,bool silent,bool onlyCheckSyntax):
Compiler(silent,onlyCheckSyntax),
mFileName(filename),
Compiler(filename, silent,onlyCheckSyntax),
mEncoding(encoding)
{
@ -25,13 +24,13 @@ bool FileCompiler::prepareForCompile()
{
log(tr("Compiling single file..."));
log("------------------");
log(tr("- Filename: %1").arg(mFileName));
log(tr("- Filename: %1").arg(mFilename));
log(tr("- Compiler Set Name: %1").arg(compilerSet()->name()));
log("");
FileType fileType = getFileType(mFileName);
mArguments= QString(" \"%1\"").arg(mFileName);
FileType fileType = getFileType(mFilename);
mArguments= QString(" \"%1\"").arg(mFilename);
if (!mOnlyCheckSyntax) {
mOutputFile = getCompiledExecutableName(mFileName);
mOutputFile = getCompiledExecutableName(mFilename);
mArguments+=QString(" -o \"%1\"").arg(mOutputFile);
//remove the old file it exists
@ -60,7 +59,7 @@ bool FileCompiler::prepareForCompile()
mCompiler = compilerSet()->cppCompiler();
break;
default:
throw CompileError(tr("Can't find the compiler for file %1").arg(mFileName));
throw CompileError(tr("Can't find the compiler for file %1").arg(mFilename));
}
mArguments += getLibraryArguments();
@ -74,3 +73,8 @@ bool FileCompiler::prepareForCompile()
log(tr("Command: %1 %2").arg(QFileInfo(mCompiler).fileName()).arg(mArguments));
return true;
}
QString FileCompiler::pipedText()
{
return QString();
}

View File

@ -15,9 +15,11 @@ protected:
bool prepareForCompile() override;
private:
QString mFileName;
QByteArray mEncoding;
// Compiler interface
protected:
QString pipedText();
};
#endif // FILECOMPILER_H

View File

@ -0,0 +1,63 @@
#include "stdincompiler.h"
#include "compilermanager.h"
#include <QFile>
#include <QFileInfo>
StdinCompiler::StdinCompiler(const QString &filename, const QString& content, bool silent, bool onlyCheckSyntax):
Compiler(filename,silent,onlyCheckSyntax),
mContent(content)
{
}
Settings::PCompilerSet StdinCompiler::compilerSet()
{
return pSettings->compilerSets().defaultSet();
}
bool StdinCompiler::prepareForCompile()
{
log(tr("Checking file syntax..."));
log("------------------");
log(tr("- Filename: %1").arg(mFilename));
log(tr("- Compiler Set Name: %1").arg(compilerSet()->name()));
log("");
FileType fileType = getFileType(mFilename);
if (fileType == FileType::Other)
fileType = FileType::CppSource;
QString strFileType;
switch(fileType) {
case FileType::CSource:
mArguments += " -x c - ";
mArguments += getCCompileArguments(mOnlyCheckSyntax);
mArguments += getCIncludeArguments();
strFileType = "C";
mCompiler = compilerSet()->CCompiler();
break;
case FileType::CppSource:
mArguments += " -x c++ - ";
mArguments += getCCompileArguments(mOnlyCheckSyntax);
mArguments += getCIncludeArguments();
strFileType = "C++";
mCompiler = compilerSet()->cppCompiler();
break;
default:
throw CompileError(tr("Can't find the compiler for file %1").arg(mFilename));
}
mArguments += getLibraryArguments();
if (!QFile(mCompiler).exists()) {
throw CompileError(tr("The Compiler '%1' doesn't exists!").arg(mCompiler));
}
log(tr("Processing %1 source file:").arg(strFileType));
log("------------------");
log(tr("%1 Compiler: %2").arg(strFileType).arg(mCompiler));
log(tr("Command: %1 %2").arg(QFileInfo(mCompiler).fileName()).arg(mArguments));
return true;
}
QString StdinCompiler::pipedText()
{
return mContent;
}

View File

@ -0,0 +1,26 @@
#ifndef STDINCOMPILER_H
#define STDINCOMPILER_H
#include "compiler.h"
class StdinCompiler : public Compiler
{
Q_OBJECT
public:
explicit StdinCompiler(const QString& filename, const QString& content, bool silent,bool onlyCheckSyntax);
// Compiler interface
protected:
Settings::PCompilerSet compilerSet() override;
bool prepareForCompile() override;
private:
QString mContent;
// Compiler interface
protected:
QString pipedText();
};
#endif // STDINCOMPILER_H

View File

@ -57,7 +57,8 @@ Editor::Editor(QWidget *parent, const QString& filename,
mInProject(inProject),
mIsNew(isNew),
mSyntaxErrorColor(QColorConstants::Red),
mSyntaxWaringColor("orange")
mSyntaxWaringColor("orange"),
mLineCount(0)
{
if (mFilename.isEmpty()) {
newfileCount++;
@ -631,6 +632,11 @@ void Editor::onModificationChanged(bool) {
void Editor::onStatusChanged(SynStatusChanges changes)
{
if (!changes.testFlag(SynStatusChange::scOpenFile) && (lines()->count()!=mLineCount)
&& (lines()->count()!=0) && ((mLineCount>0) || (lines()->count()>1))) {
pMainWindow->checkSyntaxInBack(this);
}
mLineCount = lines()->count();
// if (not (scOpenFile in Changes)) and (fText.Lines.Count <> fLineCount)
// and (fText.Lines.Count <> 0) and ((fLineCount>0) or (fText.Lines.Count>1)) then begin
// if devCodeCompletion.Enabled

View File

@ -144,6 +144,7 @@ private:
QColor mSyntaxErrorColor;
QColor mSyntaxWaringColor;
int mSyntaxErrorLine;
int mLineCount;
// QWidget interface
protected:

View File

@ -135,12 +135,12 @@ bool EditorList::isFileOpened(const QString &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)
if (e->filename().compare(filename)==0 || e->filename().compare(name)==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)
if (e->filename().compare(filename)==0 || e->filename().compare(name)==0)
return true;
}
return false;
@ -171,13 +171,13 @@ Editor* EditorList::getOpenedEditorByFilename(const QString &filename)
QString fullname = fileInfo.absoluteFilePath();
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
if (e->filename() == fullname) {
if (e->filename().compare(filename)==0 || e->filename().compare(fullname)==0) {
return e;
}
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
if (e->filename() == fullname) {
if (e->filename().compare(filename)==0 || e->filename().compare(fullname)==0) {
return e;
}
}
@ -186,15 +186,15 @@ Editor* EditorList::getOpenedEditorByFilename(const QString &filename)
Editor *EditorList::getEditorByFilename(const QString &filename)
{
QFileInfo fileInfo(filename);
QString fullname = fileInfo.absoluteFilePath();
//check if an editor is already openned
Editor* e=getOpenedEditorByFilename(fullname);
Editor* e=getOpenedEditorByFilename(filename);
if (e!=nullptr)
return e;
//Todo: check if is in the project
//Create a new editor
QFileInfo fileInfo(filename);
QString fullname = fileInfo.absoluteFilePath();
if (fileInfo.exists())
return newEditor(fullname,ENCODING_AUTO_DETECT,false,false);
return nullptr;

View File

@ -4,6 +4,7 @@
#include "editor.h"
#include "systemconsts.h"
#include "settings.h"
#include "qsynedit/Constants.h"
#include <QCloseEvent>
#include <QComboBox>
@ -47,6 +48,7 @@ MainWindow::MainWindow(QWidget *parent)
ui->EditorTabsRight->setVisible(false);
mCompilerSet = new QComboBox();
mCompilerSet->setMinimumWidth(200);
ui->toolbarCompilerSet->addWidget(mCompilerSet);
connect(mCompilerSet,QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MainWindow::onCompilerSetChanged);
@ -255,6 +257,45 @@ void MainWindow::updateCompilerSet()
mCompilerSet->setCurrentIndex(index);
}
void MainWindow::checkSyntaxInBack(Editor *e)
{
if (e==nullptr)
return;
// if not devEditor.AutoCheckSyntax then
// Exit;
//not c or cpp file
if (!e->highlighter() || e->highlighter()->getName()!=SYN_HIGHLIGHTER_CPP)
return;
if (mCompilerManager->backgroundSyntaxChecking())
return;
if (mCompilerManager->compiling())
return;
// if not Assigned(devCompilerSets.CompilationSet) then
// Exit;
// if fCompiler.Compiling then
// Exit;
// if fSyntaxChecker.Compiling then
// Exit;
if (mCheckSyntaxInBack)
return;
mCheckSyntaxInBack=true;
e->clearSyntaxIssues();
ui->tableIssues->clearIssues();
mCompilerManager->checkSyntax(e->filename(),e->lines()->text());
// if not PrepareForCompile(cttStdin,True) then begin
// fCheckSyntaxInBack:=False;
// Exit;
// end;
// if e.InProject then begin
// if not assigned(MainForm.fProject) then
// Exit;
// fSyntaxChecker.Project := MainForm.fProject;
// end;
// fSyntaxChecker.CheckSyntax(True);
}
void MainWindow::openCloseMessageSheet(bool open)
{
// if Assigned(fReportToolWindow) then
@ -436,8 +477,7 @@ void MainWindow::onCompileFinished()
Editor * e = mEditorList->getEditor();
if (e!=nullptr) {
e->beginUpdate();
e->endUpdate();
e->invalidate();
}
// Jump to problem location, sorted by significance
@ -490,6 +530,7 @@ void MainWindow::on_actionCompile_triggered()
{
Editor * editor = mEditorList->getEditor();
if (editor != NULL ) {
editor->clearSyntaxIssues();
ui->tableIssues->clearIssues();
mCompilerManager->compile(editor->filename(),editor->fileEncoding());
}

View File

@ -4,7 +4,6 @@
#include <QMainWindow>
#include "common.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
@ -13,6 +12,7 @@ class EditorList;
class QLabel;
class QComboBox;
class CompilerManager;
class Editor;
class MainWindow : public QMainWindow
{
@ -28,6 +28,8 @@ public:
void updateEditorSettings();
void updateEditorActions();
void updateEditorColorSchemes();
void updateCompilerSet();
void checkSyntaxInBack(Editor* e);
void applySettings();
@ -102,8 +104,6 @@ public slots:
private:
void setupActions();
void updateCompilerSet();
void openCloseMessageSheet(bool open);
private:

View File

@ -540,6 +540,7 @@ SynFontStyles getFontStyles(const QFont &font)
styles.setFlag(SynFontStyle::fsItalic, font.italic());
styles.setFlag(SynFontStyle::fsUnderline, font.underline());
styles.setFlag(SynFontStyle::fsStrikeOut, font.strikeOut());
return styles;
}
bool isWordChar(const QChar& ch) {

View File

@ -1860,6 +1860,9 @@ void Settings::CompilerSets::saveSets()
for (int i=0;i<mList.size();i++) {
saveSet(i);
}
if (mDefaultIndex>=mList.size()) {
mDefaultIndex = mList.size()-1;
}
mSettings->mSettings.beginGroup(SETTING_COMPILTER_SETS);
mSettings->mSettings.setValue(SETTING_COMPILTER_SETS_DEFAULT_INDEX,mDefaultIndex);
mSettings->mSettings.setValue(SETTING_COMPILTER_SETS_COUNT,mList.size());
@ -1888,8 +1891,7 @@ void Settings::CompilerSets::loadSets()
+"<br /><br />"
+msg
+"Would you like Dev-C++ to remove them for you and add the default paths to the valid paths?<br /><br />Leaving those directories will lead to problems during compilation.<br /><br />Unless you know exactly what you're doing, it is recommended that you click Yes.",
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Ok) {
clearSets();
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
findSets();
saveSets();
if ( mList.size() <= mDefaultIndex)

View File

@ -139,6 +139,7 @@ void CompilerSetOptionWidget::doSave()
saveCurrentCompilerSet();
}
pSettings->compilerSets().saveSets();
pMainWindow->updateCompilerSet();
}
void CompilerSetOptionWidget::on_cbCompilerSet_currentIndexChanged(int index)
@ -219,6 +220,7 @@ void CompilerSetOptionWidget::on_btnFindCompilers_pressed()
pSettings->compilerSets().clearSets();
pSettings->compilerSets().findSets();
doLoad();
setSettingsChanged();
if (pSettings->compilerSets().size()==0) {
QMessageBox::warning(this,tr("Failed"),tr("Can't find any compiler."));
}