- fix: Current editor wouldn't get parsed, when it's switched from another editor being parsed.
- enhancement: Support macro in #include preprocessing statements. (Issue #497)
This commit is contained in:
parent
e9f7d42aa6
commit
67b2ec1bc7
1
NEWS.md
1
NEWS.md
|
@ -154,6 +154,7 @@ Red Panda C++ Version 2.27
|
||||||
- enhancement: New code format option: "Remove superfluous empty lines exceeding"
|
- enhancement: New code format option: "Remove superfluous empty lines exceeding"
|
||||||
- enhancement: New code format option: "Remove superfluous spaces"
|
- enhancement: New code format option: "Remove superfluous spaces"
|
||||||
- change: Remove code format option: "Delete continuous empty lines"
|
- change: Remove code format option: "Delete continuous empty lines"
|
||||||
|
- fix: Current editor wouldn't get parsed, when it's switched from another editor being parsed.
|
||||||
|
|
||||||
Red Panda C++ Version 2.26
|
Red Panda C++ Version 2.26
|
||||||
- enhancement: Code suggestion for embedded std::vectors.
|
- enhancement: Code suggestion for embedded std::vectors.
|
||||||
|
|
|
@ -4064,10 +4064,10 @@ Editor::TipType Editor::getTipType(QPoint point, QSynedit::BufferCoord& pos)
|
||||||
// do not allow when dragging selection
|
// do not allow when dragging selection
|
||||||
if (isPointInSelection(pos))
|
if (isPointInSelection(pos))
|
||||||
return TipType::Selection;
|
return TipType::Selection;
|
||||||
} else if (mParser && mParser->isIncludeLine(lineText(pos.line))) {
|
|
||||||
return TipType::Preprocessor;
|
|
||||||
} else if (attr->tokenType() == QSynedit::TokenType::Identifier) {
|
} else if (attr->tokenType() == QSynedit::TokenType::Identifier) {
|
||||||
return TipType::Identifier;
|
return TipType::Identifier;
|
||||||
|
} else if (mParser && mParser->isIncludeLine(lineText(pos.line))) {
|
||||||
|
return TipType::Preprocessor;
|
||||||
} else if (attr->tokenType() == QSynedit::TokenType::Number) {
|
} else if (attr->tokenType() == QSynedit::TokenType::Number) {
|
||||||
return TipType::Number;
|
return TipType::Number;
|
||||||
} else if (attr->tokenType() == QSynedit::TokenType::Keyword) {
|
} else if (attr->tokenType() == QSynedit::TokenType::Keyword) {
|
||||||
|
|
|
@ -1681,14 +1681,17 @@ void MainWindow::setProjectCurrentFile(const QString &filename)
|
||||||
void MainWindow::openFiles(const QStringList &files)
|
void MainWindow::openFiles(const QStringList &files)
|
||||||
{
|
{
|
||||||
mOpeningFiles=true;
|
mOpeningFiles=true;
|
||||||
auto action=finally([this]{
|
|
||||||
mOpeningFiles=false;
|
|
||||||
});
|
|
||||||
mEditorList->beginUpdate();
|
mEditorList->beginUpdate();
|
||||||
mOpenningFiles = true;
|
|
||||||
auto end = finally([this] {
|
auto end = finally([this] {
|
||||||
this->mEditorList->endUpdate();
|
this->mEditorList->endUpdate();
|
||||||
mOpenningFiles = false;
|
mOpeningFiles=false;
|
||||||
|
Editor* e=mEditorList->getEditor();
|
||||||
|
if (e) {
|
||||||
|
e->reparse(false);
|
||||||
|
e->checkSyntaxInBack();
|
||||||
|
e->reparseTodo();
|
||||||
|
e->activate();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
//Check if there is a project file in the list and open it
|
//Check if there is a project file in the list and open it
|
||||||
for (const QString& file:files) {
|
for (const QString& file:files) {
|
||||||
|
@ -1704,14 +1707,6 @@ void MainWindow::openFiles(const QStringList &files)
|
||||||
if (files.length()>0) {
|
if (files.length()>0) {
|
||||||
openFile(files.last(),true);
|
openFile(files.last(),true);
|
||||||
}
|
}
|
||||||
mEditorList->endUpdate();
|
|
||||||
Editor* e=mEditorList->getEditor();
|
|
||||||
if (e) {
|
|
||||||
e->reparse(false);
|
|
||||||
e->checkSyntaxInBack();
|
|
||||||
e->reparseTodo();
|
|
||||||
e->activate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor* MainWindow::openFile(QString filename, bool activate, QTabWidget* page)
|
Editor* MainWindow::openFile(QString filename, bool activate, QTabWidget* page)
|
||||||
|
|
|
@ -995,22 +995,40 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo
|
||||||
return;
|
return;
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
if (mParsing || mLockCount>0)
|
if (mParsing) {
|
||||||
|
mLastParseFileCommand = std::make_unique<ParseFileCommand>();
|
||||||
|
mLastParseFileCommand->fileName = fileName;
|
||||||
|
mLastParseFileCommand->inProject = inProject;
|
||||||
|
mLastParseFileCommand->onlyIfNotParsed = onlyIfNotParsed;
|
||||||
|
mLastParseFileCommand->updateView = updateView;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mLockCount>0)
|
||||||
return;
|
return;
|
||||||
updateSerialId();
|
|
||||||
mParsing = true;
|
mParsing = true;
|
||||||
|
updateSerialId();
|
||||||
if (updateView)
|
if (updateView)
|
||||||
emit onBusy();
|
emit onBusy();
|
||||||
emit onStartParsing();
|
emit onStartParsing();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto action = finally([&,this]{
|
auto action = finally([&,this]{
|
||||||
mParsing = false;
|
QMutexLocker locker(&mMutex);
|
||||||
|
|
||||||
if (updateView)
|
if (updateView)
|
||||||
emit onEndParsing(mFilesScannedCount,1);
|
emit onEndParsing(mFilesScannedCount,1);
|
||||||
else
|
else
|
||||||
emit onEndParsing(mFilesScannedCount,0);
|
emit onEndParsing(mFilesScannedCount,0);
|
||||||
|
|
||||||
|
if (mLastParseFileCommand) {
|
||||||
|
mParsing = false;
|
||||||
|
::parseFile(PCppParser{this},
|
||||||
|
mLastParseFileCommand->fileName,
|
||||||
|
mLastParseFileCommand->inProject,
|
||||||
|
mLastParseFileCommand->onlyIfNotParsed,
|
||||||
|
mLastParseFileCommand->updateView);
|
||||||
|
mLastParseFileCommand = nullptr;
|
||||||
|
}
|
||||||
|
mParsing = false;
|
||||||
});
|
});
|
||||||
QString fName = fileName;
|
QString fName = fileName;
|
||||||
if (onlyIfNotParsed && mPreprocessor.fileScanned(fName))
|
if (onlyIfNotParsed && mPreprocessor.fileScanned(fName))
|
||||||
|
@ -1040,15 +1058,6 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo
|
||||||
emit onProgress(fileName,mFilesToScanCount,mFilesScannedCount);
|
emit onProgress(fileName,mFilesToScanCount,mFilesScannedCount);
|
||||||
internalParse(fileName);
|
internalParse(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (inProject)
|
|
||||||
// mProjectFiles.insert(fileName);
|
|
||||||
// else {
|
|
||||||
// mProjectFiles.remove(fileName);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Parse from disk or stream
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6758,7 +6767,7 @@ CppFileParserThread::CppFileParserThread(
|
||||||
|
|
||||||
void CppFileParserThread::run()
|
void CppFileParserThread::run()
|
||||||
{
|
{
|
||||||
if (mParser && !mParser->parsing()) {
|
if (mParser) {
|
||||||
mParser->parseFile(mFileName,mInProject,mOnlyIfNotParsed,mUpdateView);
|
mParser->parseFile(mFileName,mInProject,mOnlyIfNotParsed,mUpdateView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,15 @@ class CppParser : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
struct ParseFileCommand {
|
||||||
|
QString fileName;
|
||||||
|
bool inProject;
|
||||||
|
bool onlyIfNotParsed;
|
||||||
|
bool updateView;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PParseFileCommand = std::unique_ptr<ParseFileCommand>;
|
||||||
explicit CppParser(QObject *parent = nullptr);
|
explicit CppParser(QObject *parent = nullptr);
|
||||||
CppParser(const CppParser&)=delete;
|
CppParser(const CppParser&)=delete;
|
||||||
CppParser& operator=(const CppParser)=delete;
|
CppParser& operator=(const CppParser)=delete;
|
||||||
|
@ -732,6 +741,8 @@ private:
|
||||||
QRecursiveMutex mMutex;
|
QRecursiveMutex mMutex;
|
||||||
QMap<QString,KeywordType> mCppKeywords;
|
QMap<QString,KeywordType> mCppKeywords;
|
||||||
QSet<QString> mCppTypeKeywords;
|
QSet<QString> mCppTypeKeywords;
|
||||||
|
|
||||||
|
PParseFileCommand mLastParseFileCommand;
|
||||||
};
|
};
|
||||||
using PCppParser = std::shared_ptr<CppParser>;
|
using PCppParser = std::shared_ptr<CppParser>;
|
||||||
|
|
||||||
|
|
|
@ -380,9 +380,27 @@ void CppPreprocessor::handleInclude(const QString &line, bool fromNext)
|
||||||
includes = mIncludePathList;
|
includes = mIncludePathList;
|
||||||
projectIncludes = mProjectIncludePathList;
|
projectIncludes = mProjectIncludePathList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int i=1; // skip '#'
|
||||||
|
int len=line.length();
|
||||||
|
//skip spaces
|
||||||
|
while (i<len && isSpaceChar(line[i]))
|
||||||
|
i++;
|
||||||
|
//skip 'include'
|
||||||
|
while (i<len && isIdentChar(line[i]))
|
||||||
|
i++;
|
||||||
|
//skip spaces
|
||||||
|
while (i<len && isSpaceChar(line[i]))
|
||||||
|
i++;
|
||||||
|
if (i>=line.length())
|
||||||
|
return;
|
||||||
|
QString s=line.mid(i);
|
||||||
|
QSet<QString> usedMacros;
|
||||||
|
s = expandMacros(s, usedMacros);
|
||||||
|
|
||||||
fileName = getHeaderFilename(
|
fileName = getHeaderFilename(
|
||||||
file->fileName,
|
file->fileName,
|
||||||
line,
|
s,
|
||||||
includes,
|
includes,
|
||||||
projectIncludes);
|
projectIncludes);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue