- 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
This commit is contained in:
Roy Qu 2022-03-27 11:44:52 +08:00
parent 7c218b7d5a
commit ac54496aeb
16 changed files with 207 additions and 74 deletions

View File

@ -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"

View File

@ -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;
}

View File

@ -188,7 +188,7 @@ void CompilerManager::buildProjectMakefile(std::shared_ptr<Project> project)
}
void CompilerManager::checkSyntax(const QString &filename, const QString &content, bool isAscii, std::shared_ptr<Project> project)
void CompilerManager::checkSyntax(const QString &filename, const QByteArray& encoding, const QString &content, std::shared_ptr<Project> 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();
}

View File

@ -41,7 +41,7 @@ public:
void compileProject(std::shared_ptr<Project> project, bool rebuild, bool silent=false,bool onlyCheckSyntax=false);
void cleanProject(std::shared_ptr<Project> project);
void buildProjectMakefile(std::shared_ptr<Project> project);
void checkSyntax(const QString&filename, const QString& content, bool isAscii, std::shared_ptr<Project> project);
void checkSyntax(const QString&filename, const QByteArray& encoding, const QString& content, std::shared_ptr<Project> 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<POJProblemCase> problemCases);

View File

@ -24,7 +24,9 @@
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
const QVector<POJProblemCase>& 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:"<<process.error();
switch (process.error()) {
case QProcess::FailedToStart:
emit runErrorOccurred(tr("The runner process '%1' failed to start.").arg(mFilename));
break;
// case QProcess::Crashed:
// if (!mStop)
// emit runErrorOccurred(tr("The runner process crashed after starting successfully."));
// break;
case QProcess::Timedout:
emit runErrorOccurred(tr("The last waitFor...() function timed out."));
break;
case QProcess::WriteError:
emit runErrorOccurred(tr("An error occurred when attempting to write to the runner process."));
break;
case QProcess::ReadError:
emit runErrorOccurred(tr("An error occurred when attempting to read from the runner process."));
break;
default:
break;
if (mExecTimeouted) {
problemCase->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:"<<process.error();
switch (process.error()) {
case QProcess::FailedToStart:
emit runErrorOccurred(tr("The runner process '%1' failed to start.").arg(mFilename));
break;
// case QProcess::Crashed:
// if (!mStop)
// emit runErrorOccurred(tr("The runner process crashed after starting successfully."));
// break;
case QProcess::Timedout:
emit runErrorOccurred(tr("The last waitFor...() function timed out."));
break;
case QProcess::WriteError:
emit runErrorOccurred(tr("An error occurred when attempting to write to the runner process."));
break;
case QProcess::ReadError:
emit runErrorOccurred(tr("An error occurred when attempting to read from the runner process."));
break;
default:
break;
}
}
problemCase->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;

View File

@ -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

View File

@ -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));

View File

@ -20,10 +20,10 @@
#include <QFileInfo>
#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 - ";

View File

@ -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

View File

@ -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,

View File

@ -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();

View File

@ -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));

View File

@ -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);
}

View File

@ -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;

View File

@ -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();
}

View File

@ -73,19 +73,63 @@
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<widget class="QGroupBox" name="grpEnableTimeout">
<property name="title">
<string>Timeout for Case Valdation</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="spinCaseTimeout">
<property name="specialValueText">
<string/>
</property>
<property name="suffix">
<string>Sec</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Case Editor Font</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
<number>7</number>
</property>
<property name="topMargin">
<number>0</number>
<number>7</number>
</property>
<property name="rightMargin">
<number>0</number>
<number>7</number>
</property>
<property name="bottomMargin">
<number>0</number>
<number>7</number>
</property>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
@ -94,13 +138,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Font:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QWidget" name="widget_3" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
@ -135,6 +172,13 @@
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Font:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
@ -173,16 +217,16 @@
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="chkOnlyMonospaced">
<property name="text">
<string>Only Monospaced</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkOnlyMonospaced">
<property name="text">
<string>Only Monospaced</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">