From ac54496aebc39d8c496740e511ccd9134adb1560 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sun, 27 Mar 2022 11:44:52 +0800 Subject: [PATCH] - fix: auto syntax check use wrong charset, if a file in editing is not encoded with ANSI encoding - enhancement: timeout for problem case test in --- NEWS.md | 2 + RedPandaIDE/compiler/compiler.cpp | 5 +- RedPandaIDE/compiler/compilermanager.cpp | 8 +- RedPandaIDE/compiler/compilermanager.h | 2 +- RedPandaIDE/compiler/ojproblemcasesrunner.cpp | 90 +++++++++++++------ RedPandaIDE/compiler/ojproblemcasesrunner.h | 14 ++- RedPandaIDE/compiler/projectcompiler.cpp | 12 +-- RedPandaIDE/compiler/stdincompiler.cpp | 8 +- RedPandaIDE/compiler/stdincompiler.h | 6 +- RedPandaIDE/mainwindow.cpp | 11 ++- RedPandaIDE/mainwindow.h | 1 + RedPandaIDE/project.cpp | 4 +- RedPandaIDE/settings.cpp | 24 +++++ RedPandaIDE/settings.h | 8 ++ .../executorproblemsetwidget.cpp | 4 + .../executorproblemsetwidget.ui | 82 +++++++++++++---- 16 files changed, 207 insertions(+), 74 deletions(-) diff --git a/NEWS.md b/NEWS.md index 69baea76..021ba193 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,8 @@ Red Panda C++ Version 1.0.2 - enhancement: better display when input with IM under column mode - enhancement: better display current lines under column mode - change: test to use utf-8 as the default encoding (prepare to use libclang to implement parser) + - fix: auto syntax check use wrong charset, if a file in editing is not encoded with ANSI encoding + - enhancement: timeout for problem case test in Red Panda C++ Version 1.0.1 - fix: only convert project icon file when it's filename doesn't end with ".ico" diff --git a/RedPandaIDE/compiler/compiler.cpp b/RedPandaIDE/compiler/compiler.cpp index a84fa2cb..a09f747d 100644 --- a/RedPandaIDE/compiler/compiler.cpp +++ b/RedPandaIDE/compiler/compiler.cpp @@ -297,8 +297,9 @@ QString Compiler::getCharsetArgument(const QByteArray& encoding) } else { execEncodingName = compilerSetExecCharset; } - result += QString(" -finput-charset=%1 -fexec-charset=%2") - .arg(encodingName, execEncodingName); + if (encodingName!=execEncodingName) + result += QString(" -finput-charset=%1 -fexec-charset=%2") + .arg(encodingName, execEncodingName); } return result; } diff --git a/RedPandaIDE/compiler/compilermanager.cpp b/RedPandaIDE/compiler/compilermanager.cpp index 3097ffd0..60a3c7f9 100644 --- a/RedPandaIDE/compiler/compilermanager.cpp +++ b/RedPandaIDE/compiler/compilermanager.cpp @@ -188,7 +188,7 @@ void CompilerManager::buildProjectMakefile(std::shared_ptr project) } -void CompilerManager::checkSyntax(const QString &filename, const QString &content, bool isAscii, std::shared_ptr project) +void CompilerManager::checkSyntax(const QString &filename, const QByteArray& encoding, const QString &content, std::shared_ptr project) { if (!pSettings->compilerSets().defaultSet()) { QMessageBox::critical(pMainWindow, @@ -204,7 +204,8 @@ void CompilerManager::checkSyntax(const QString &filename, const QString &conten mSyntaxCheckErrorCount = 0; mSyntaxCheckIssueCount = 0; - mBackgroundSyntaxChecker = new StdinCompiler(filename,content,isAscii,true,true); + StdinCompiler *pStdinCompiler = new StdinCompiler(filename,encoding, content,true,true); + mBackgroundSyntaxChecker = pStdinCompiler; mBackgroundSyntaxChecker->setProject(project); connect(mBackgroundSyntaxChecker, &Compiler::finished, mBackgroundSyntaxChecker, &QThread::deleteLater); connect(mBackgroundSyntaxChecker, &Compiler::compileIssue, this, &CompilerManager::onSyntaxCheckIssue); @@ -326,12 +327,15 @@ void CompilerManager::runProblem(const QString &filename, const QString &argumen } OJProblemCasesRunner * execRunner = new OJProblemCasesRunner(filename,arguments,workDir,problemCases); mRunner = execRunner; + if (pSettings->executor().enableCaseTimeout()) + execRunner->setExecTimeout(pSettings->executor().caseTimeout()*1000); connect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated); connect(mRunner, &Runner::finished, pMainWindow ,&MainWindow::onRunProblemFinished); connect(mRunner, &Runner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured); connect(execRunner, &OJProblemCasesRunner::caseStarted, pMainWindow, &MainWindow::onOJProblemCaseStarted); connect(execRunner, &OJProblemCasesRunner::caseFinished, pMainWindow, &MainWindow::onOJProblemCaseFinished); connect(execRunner, &OJProblemCasesRunner::newOutputGetted, pMainWindow, &MainWindow::onOJProblemCaseNewOutputGetted); + connect(execRunner, &OJProblemCasesRunner::resetOutput, pMainWindow, &MainWindow::onOJProblemCaseResetOutput); mRunner->start(); } diff --git a/RedPandaIDE/compiler/compilermanager.h b/RedPandaIDE/compiler/compilermanager.h index 2fa563fb..3cd7f1c6 100644 --- a/RedPandaIDE/compiler/compilermanager.h +++ b/RedPandaIDE/compiler/compilermanager.h @@ -41,7 +41,7 @@ public: void compileProject(std::shared_ptr project, bool rebuild, bool silent=false,bool onlyCheckSyntax=false); void cleanProject(std::shared_ptr project); void buildProjectMakefile(std::shared_ptr project); - void checkSyntax(const QString&filename, const QString& content, bool isAscii, std::shared_ptr project); + void checkSyntax(const QString&filename, const QByteArray& encoding, const QString& content, std::shared_ptr project); void run(const QString& filename, const QString& arguments, const QString& workDir); void runProblem(const QString& filename, const QString& arguments, const QString& workDir, POJProblemCase problemCase); void runProblem(const QString& filename, const QString& arguments, const QString& workDir, QVector problemCases); diff --git a/RedPandaIDE/compiler/ojproblemcasesrunner.cpp b/RedPandaIDE/compiler/ojproblemcasesrunner.cpp index b0d67c0a..96d9188c 100644 --- a/RedPandaIDE/compiler/ojproblemcasesrunner.cpp +++ b/RedPandaIDE/compiler/ojproblemcasesrunner.cpp @@ -24,7 +24,9 @@ OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir, const QVector& problemCases, QObject *parent): - Runner(filename,arguments,workDir,parent) + Runner(filename,arguments,workDir,parent), + mExecTimeout(-1), + mExecTimeouted(false) { mProblemCases = problemCases; mBufferSize = 8192; @@ -34,7 +36,9 @@ OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QStrin OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir, POJProblemCase problemCase, QObject *parent): - Runner(filename,arguments,workDir,parent) + Runner(filename,arguments,workDir,parent), + mExecTimeout(-1), + mExecTimeouted(false) { mProblemCases.append(problemCase); mBufferSize = 8192; @@ -87,6 +91,8 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase) QByteArray buffer; QByteArray output; int noOutputTime = 0; + QElapsedTimer elapsedTimer; + elapsedTimer.start(); while (true) { process.waitForFinished(mWaitForFinishTime); readed = process.read(mBufferSize); @@ -94,7 +100,13 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase) if (process.state()!=QProcess::Running) { break; } - if (mStop) { + if (mExecTimeout>0) { + int msec = elapsedTimer.elapsed(); + if (msec>mExecTimeout) { + mExecTimeouted=true; + } + } + if (mStop || mExecTimeouted) { process.closeReadChannel(QProcess::StandardOutput); process.closeReadChannel(QProcess::StandardError); process.closeWriteChannel(); @@ -115,34 +127,39 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase) noOutputTime += mWaitForFinishTime; } } - if (process.state() == QProcess::ProcessState::NotRunning) - buffer += process.readAll(); - emit newOutputGetted(problemCase->getId(),QString::fromLocal8Bit(buffer)); - output.append(buffer); - if (errorOccurred) { - //qDebug()<<"process error:"<output = tr("Case Timeout"); + emit resetOutput(problemCase->getId(), problemCase->output); + } else { + if (process.state() == QProcess::ProcessState::NotRunning) + buffer += process.readAll(); + emit newOutputGetted(problemCase->getId(),QString::fromLocal8Bit(buffer)); + output.append(buffer); + if (errorOccurred) { + //qDebug()<<"process error:"<output = QString::fromLocal8Bit(output); } - problemCase->output = QString::fromLocal8Bit(output); } void OJProblemCasesRunner::run() @@ -159,6 +176,21 @@ void OJProblemCasesRunner::run() } } +bool OJProblemCasesRunner::execTimeouted() const +{ + return mExecTimeouted; +} + +int OJProblemCasesRunner::execTimeout() const +{ + return mExecTimeout; +} + +void OJProblemCasesRunner::setExecTimeout(int newExecTimeout) +{ + mExecTimeout = newExecTimeout; +} + int OJProblemCasesRunner::waitForFinishTime() const { return mWaitForFinishTime; diff --git a/RedPandaIDE/compiler/ojproblemcasesrunner.h b/RedPandaIDE/compiler/ojproblemcasesrunner.h index 0a91cd20..5acd4290 100644 --- a/RedPandaIDE/compiler/ojproblemcasesrunner.h +++ b/RedPandaIDE/compiler/ojproblemcasesrunner.h @@ -40,10 +40,16 @@ public: int waitForFinishTime() const; void setWaitForFinishTime(int newWaitForFinishTime); + int execTimeout() const; + void setExecTimeout(int newExecTimeout); + + bool execTimeouted() const; + signals: - void caseStarted(const QString& id, int current, int total); - void caseFinished(const QString& id, int current, int total); - void newOutputGetted(const QString&id, const QString& newOutputLine); + void caseStarted(const QString &caseId, int current, int total); + void caseFinished(const QString &caseId, int current, int total); + void newOutputGetted(const QString &caseId, const QString &newOutputLine); + void resetOutput(const QString &caseId, const QString &newOutputLine); private: void runCase(int index, POJProblemCase problemCase); private: @@ -55,6 +61,8 @@ protected: private: int mBufferSize; int mOutputRefreshTime; + int mExecTimeout; + bool mExecTimeouted; }; #endif // OJPROBLEMCASESRUNNER_H diff --git a/RedPandaIDE/compiler/projectcompiler.cpp b/RedPandaIDE/compiler/projectcompiler.cpp index ddfe1124..26ce0db9 100644 --- a/RedPandaIDE/compiler/projectcompiler.cpp +++ b/RedPandaIDE/compiler/projectcompiler.cpp @@ -357,15 +357,17 @@ void ProjectCompiler::writeMakeObjFilesRules(QFile &file) QByteArray defaultSystemEncoding = pCharsetInfoManager->getDefaultSystemEncoding(); if (unit->encoding() == ENCODING_AUTO_DETECT) { Editor* editor = mProject->unitEditor(unit); - if (editor && editor->fileEncoding()!=ENCODING_ASCII) + if (editor && editor->fileEncoding()!=ENCODING_ASCII + && editor->fileEncoding()!=defaultSystemEncoding) encodingStr = QString(" -finput-charset=%1 -fexec-charset=%2") .arg(QString(editor->fileEncoding()), QString(defaultSystemEncoding)); } else if (unit->encoding()==ENCODING_SYSTEM_DEFAULT) { - encodingStr = QString(" -finput-charset=%1 -fexec-charset=%2") - .arg(QString(defaultSystemEncoding), - QString(defaultSystemEncoding)); - } else if (unit->encoding()!=ENCODING_ASCII && !unit->encoding().isEmpty()) { +// encodingStr = QString(" -finput-charset=%1 -fexec-charset=%2") +// .arg(QString(defaultSystemEncoding), +// QString(defaultSystemEncoding)); + } else if (unit->encoding()!=ENCODING_ASCII && !unit->encoding().isEmpty() + && unit->encoding()!=defaultSystemEncoding) { encodingStr = QString(" -finput-charset=%1 -fexec-charset=%2") .arg(QString(unit->encoding()), QString(defaultSystemEncoding)); diff --git a/RedPandaIDE/compiler/stdincompiler.cpp b/RedPandaIDE/compiler/stdincompiler.cpp index 1d164bf7..dbc81d1b 100644 --- a/RedPandaIDE/compiler/stdincompiler.cpp +++ b/RedPandaIDE/compiler/stdincompiler.cpp @@ -20,10 +20,10 @@ #include #include "../platform.h" -StdinCompiler::StdinCompiler(const QString &filename, const QString& content,bool isAscii, bool silent, bool onlyCheckSyntax): +StdinCompiler::StdinCompiler(const QString &filename,const QByteArray& encoding, const QString& content,bool silent, bool onlyCheckSyntax): Compiler(filename,silent,onlyCheckSyntax), mContent(content), - mIsAscii(isAscii) + mEncoding(encoding) { } @@ -39,8 +39,8 @@ bool StdinCompiler::prepareForCompile() if (fileType == FileType::Other) fileType = FileType::CppSource; QString strFileType; - if (!mIsAscii) - mArguments += getCharsetArgument(pCharsetInfoManager->getDefaultSystemEncoding()); + if (mEncoding!=ENCODING_ASCII && (!mOnlyCheckSyntax || mEncoding != ENCODING_UTF8 )) + mArguments += getCharsetArgument(mEncoding); switch(fileType) { case FileType::CSource: mArguments += " -x c - "; diff --git a/RedPandaIDE/compiler/stdincompiler.h b/RedPandaIDE/compiler/stdincompiler.h index fb7c1083..b43f3569 100644 --- a/RedPandaIDE/compiler/stdincompiler.h +++ b/RedPandaIDE/compiler/stdincompiler.h @@ -24,15 +24,14 @@ class StdinCompiler : public Compiler Q_OBJECT public: - explicit StdinCompiler(const QString& filename, const QString& content, bool isAscii, bool silent,bool onlyCheckSyntax); + explicit StdinCompiler(const QString& filename, const QByteArray& encoding, const QString& content, bool silent,bool onlyCheckSyntax); - // Compiler interface protected: bool prepareForCompile() override; private: QString mContent; - bool mIsAscii; + QByteArray mEncoding; // Compiler interface protected: @@ -41,6 +40,7 @@ protected: // Compiler interface protected: bool prepareForRebuild() override; + }; #endif // STDINCOMPILER_H diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index ef6629a9..9b4226c3 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1459,11 +1459,9 @@ void MainWindow::checkSyntaxInBack(Editor *e) clearIssues(); CompileTarget target =getCompileTarget(); if (target ==CompileTarget::Project) { - mCompilerManager->checkSyntax(e->filename(),e->text(), - e->fileEncoding() == ENCODING_ASCII, mProject); + mCompilerManager->checkSyntax(e->filename(), e->fileEncoding(), e->text(), mProject); } else { - mCompilerManager->checkSyntax(e->filename(),e->text(), - e->fileEncoding() == ENCODING_ASCII, nullptr); + mCompilerManager->checkSyntax(e->filename(),e->fileEncoding(),e->text(), nullptr); } } @@ -4530,6 +4528,11 @@ void MainWindow::onOJProblemCaseNewOutputGetted(const QString &/* id */, const Q ui->txtProblemCaseOutput->appendPlainText(line); } +void MainWindow::onOJProblemCaseResetOutput(const QString &id, const QString &line) +{ + ui->txtProblemCaseOutput->setPlainText(line); +} + void MainWindow::cleanUpCPUDialog() { disconnect(mCPUDialog,&CPUDialog::closed, diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 7be9e629..3c05d0ba 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -202,6 +202,7 @@ public slots: void onOJProblemCaseStarted(const QString& id, int current, int total); void onOJProblemCaseFinished(const QString& id, int current, int total); void onOJProblemCaseNewOutputGetted(const QString& id, const QString& line); + void onOJProblemCaseResetOutput(const QString& id, const QString& line); void cleanUpCPUDialog(); void onDebugCommandInput(const QString& command); void onDebugEvaluateInput(); diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index 230b911d..72d80a03 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -892,10 +892,10 @@ PProjectUnit Project::addUnit(const QString &inFileName, PProjectModelNode paren newUnit->setNew(false); Editor * e= unitEditor(newUnit); if (e) { - newUnit->setEncoding(e->encodingOption()); + newUnit->setEncoding(e->fileEncoding()); e->setInProject(true); } else { - newUnit->setEncoding(ENCODING_AUTO_DETECT); + newUnit->setEncoding(pSettings->editor().defaultEncoding()); } newUnit->setFolder(getFolderPath(parentNode)); newUnit->setNode(makeNewFileNode(extractFileName(newUnit->fileName()), false, parentNode)); diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index af7cd942..04c4d802 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -3227,6 +3227,26 @@ void Settings::Executor::setCaseEditorFontOnlyMonospaced(bool newCaseEditorFontO mCaseEditorFontOnlyMonospaced = newCaseEditorFontOnlyMonospaced; } +int Settings::Executor::caseTimeout() const +{ + return mCaseTimeout; +} + +void Settings::Executor::setCaseTimeout(int newCaseTimeout) +{ + mCaseTimeout = newCaseTimeout; +} + +bool Settings::Executor::enableCaseTimeout() const +{ + return mEnableCaseTimeout; +} + +void Settings::Executor::setEnableCaseTimeout(bool newEnableCaseTimeout) +{ + mEnableCaseTimeout = newEnableCaseTimeout; +} + int Settings::Executor::caseEditorFontSize() const { return mCaseEditorFontSize; @@ -3283,6 +3303,8 @@ void Settings::Executor::doSave() saveValue("case_editor_font_name",mCaseEditorFontName); saveValue("case_editor_font_size",mCaseEditorFontSize); saveValue("case_editor_font_only_monospaced",mCaseEditorFontOnlyMonospaced); + saveValue("case_timeout", mCaseTimeout); + saveValue("enable_case_timeout", mEnableCaseTimeout); } bool Settings::Executor::pauseConsole() const @@ -3315,6 +3337,8 @@ void Settings::Executor::doLoad() #endif mCaseEditorFontSize = intValue("case_editor_font_size",12); mCaseEditorFontOnlyMonospaced = boolValue("case_editor_font_only_monospaced",true); + mCaseTimeout = intValue("case_timeout", 1); + mEnableCaseTimeout = boolValue("enable_case_timeout", true); } diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h index df7b8e76..350c2d6f 100644 --- a/RedPandaIDE/settings.h +++ b/RedPandaIDE/settings.h @@ -886,6 +886,12 @@ public: bool caseEditorFontOnlyMonospaced() const; void setCaseEditorFontOnlyMonospaced(bool newCaseEditorFontOnlyMonospaced); + bool enableCaseTimeout() const; + void setEnableCaseTimeout(bool newEnableCaseTimeout); + + int caseTimeout() const; + void setCaseTimeout(int newCaseTimeout); + private: // general bool mPauseConsole; @@ -903,6 +909,8 @@ public: QString mCaseEditorFontName; int mCaseEditorFontSize; bool mCaseEditorFontOnlyMonospaced; + bool mEnableCaseTimeout; + int mCaseTimeout; protected: void doSave() override; diff --git a/RedPandaIDE/settingsdialog/executorproblemsetwidget.cpp b/RedPandaIDE/settingsdialog/executorproblemsetwidget.cpp index 3bcf41bc..7c86cf66 100644 --- a/RedPandaIDE/settingsdialog/executorproblemsetwidget.cpp +++ b/RedPandaIDE/settingsdialog/executorproblemsetwidget.cpp @@ -41,6 +41,8 @@ void ExecutorProblemSetWidget::doLoad() ui->cbFont->setCurrentFont(QFont(pSettings->executor().caseEditorFontName())); ui->spinFontSize->setValue(pSettings->executor().caseEditorFontSize()); ui->chkOnlyMonospaced->setChecked(pSettings->executor().caseEditorFontOnlyMonospaced()); + ui->grpEnableTimeout->setEnabled(pSettings->executor().enableCaseTimeout()); + ui->spinCaseTimeout->setValue(pSettings->executor().caseTimeout()); } void ExecutorProblemSetWidget::doSave() @@ -52,6 +54,8 @@ void ExecutorProblemSetWidget::doSave() pSettings->executor().setCaseEditorFontName(ui->cbFont->currentFont().family()); pSettings->executor().setCaseEditorFontOnlyMonospaced(ui->chkOnlyMonospaced->isChecked()); pSettings->executor().setCaseEditorFontSize(ui->spinFontSize->value()); + pSettings->executor().setEnableCaseTimeout(ui->grpEnableTimeout->isEnabled()); + pSettings->executor().setCaseTimeout(ui->spinCaseTimeout->value()); pSettings->executor().save(); pMainWindow->applySettings(); } diff --git a/RedPandaIDE/settingsdialog/executorproblemsetwidget.ui b/RedPandaIDE/settingsdialog/executorproblemsetwidget.ui index bd893dce..d2cd8e2b 100644 --- a/RedPandaIDE/settingsdialog/executorproblemsetwidget.ui +++ b/RedPandaIDE/settingsdialog/executorproblemsetwidget.ui @@ -73,19 +73,63 @@ - + + + Timeout for Case Valdation + + + true + + + + + + + + + Sec + + + 1 + + + 10000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Case Editor Font + - 0 + 7 - 0 + 7 - 0 + 7 - 0 + 7 @@ -94,13 +138,6 @@ - - - - Font: - - - @@ -135,6 +172,13 @@ + + + + Font: + + + @@ -173,16 +217,16 @@ + + + + Only Monospaced + + + - - - - Only Monospaced - - -