From 00da3303ac74cbb18edadcee2c1cfb70f332e124 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Wed, 11 Aug 2021 20:06:28 +0800 Subject: [PATCH] work save --- RedPandaIDE/parser/cpppreprocessor.cpp | 129 +++++++++++++++++++++++++ RedPandaIDE/parser/cpppreprocessor.h | 5 +- RedPandaIDE/parser/utils.cpp | 8 +- RedPandaIDE/parser/utils.h | 4 +- RedPandaIDE/utils.cpp | 37 +++++++ RedPandaIDE/utils.h | 1 + 6 files changed, 175 insertions(+), 9 deletions(-) diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 0828562f..8dbfb36e 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -1,6 +1,8 @@ #include "cpppreprocessor.h" #include "../utils.h" +#include + CppPreprocessor::CppPreprocessor(QObject *parent) : QObject(parent) { } @@ -266,6 +268,110 @@ PParsedFile CppPreprocessor::getInclude(int index) return mIncludes[index]; } +void CppPreprocessor::openInclude(const QString &fileName, QTextStream stream) +{ + if (mIncludes.size()>0) { + PParsedFile topFile = mIncludes.front(); + if (topFile->fileIncludes->includeFiles.contains(fileName)) { + return; //already included + } + for (PParsedFile parsedFile:mIncludes) { + parsedFile->fileIncludes->includeFiles.insert(fileName,false); + } + } + if (mIncludes.size()>0) { + // Backup old position if we're entering a new file + PParsedFile innerMostFile = mIncludes.back(); + innerMostFile->index = mIndex; + innerMostFile->branches = mBranchResults.count(); + + innerMostFile->fileIncludes->includeFiles.insert(fileName,true); + } + +// // Add the new file to the includes of the current file +// // Only add items to the include list of the given file if the file hasn't been scanned yet +// // The above is fixed by checking for duplicates. +// // The proper way would be to do backtracking of files we have FINISHED scanned. +// // These are not the same files as the ones in fScannedFiles. We have STARTED scanning these. +// { +// if Assigned(fCurrentIncludes) then +// with fCurrentIncludes^ do +// if not ContainsText(IncludeFiles, FileName) then +// IncludeFiles := IncludeFiles + AnsiQuotedStr(FileName, '"') + ','; +// } + + // Create and add new buffer/position + PParsedFile parsedFile = std::make_shared(); + parsedFile->index = 0; + parsedFile->fileName = fileName; + parsedFile->branches = 0; + // parsedFile->buffer; it's auto initialized + + + // Keep track of files we include here + // Only create new items for files we have NOT scanned yet + mCurrentIncludes = getFileIncludesEntry(fileName); + if (!mCurrentIncludes) { + // do NOT create a new item for a file that's already in the list + mCurrentIncludes = std::make_shared(); + mCurrentIncludes->baseFile = fileName; + //mCurrentIncludes->includeFiles; + //mCurrentIncludes->usings; + //mCurrentIncludes->statements; + //mCurrentIncludes->declaredStatements; + //mCurrentIncludes->scopes; + //mCurrentIncludes->dependedFiles; + //mCurrentIncludes->dependingFiles; + mIncludesList.insert(fileName,mCurrentIncludes); + } + + parsedFile->fileIncludes = mCurrentIncludes; + + // Don't parse stuff we have already parsed + if ((stream.device()!=nullptr) || !mScannedFiles.contains(fileName)) { + // Parse ONCE + //if not Assigned(Stream) then + mScannedFiles.insert(fileName); + + // Only load up the file if we are allowed to parse it + bool isSystemFile = isSystemHeaderFile(fileName, mIncludePaths); + if ((mParseSystem && isSystemFile) || (mParseLocal && !isSystemFile)) { + if (stream.device()!=nullptr) { + stream.seek(0); // start scanning from here + parsedFile->buffer = ReadStreamToLines(&stream); + } else { + parsedFile->buffer = ReadFileToLines(fileName); + } + } + } else { + //add defines of already parsed including headers; + addDefinesInFile(fileName); + PFileIncludes fileIncludes = getFileIncludesEntry(fileName); + for (PParsedFile file:mIncludes) { + file->fileIncludes->includeFiles.insert(fileIncludes->includeFiles); + } + } + mIncludes.append(parsedFile); + + // Process it + mIndex = parsedFile->index; + mFileName = parsedFile->fileName; + mBuffer = parsedFile->buffer; + + // Trim all lines + for (int i=0;i1) { // include from within a file + mResult[mPreProcIndex] = includeLine; + } else { + mResult.append(includeLine); + } +} + void CppPreprocessor::closeInclude() { @@ -305,6 +411,12 @@ bool CppPreprocessor::getCurrentBranch() return true; } +void CppPreprocessor::removeCurrentBranch() +{ + if (mBranchResults.size()>0) + mBranchResults.pop_back(); +} + QString CppPreprocessor::getResult() { QString s; @@ -348,6 +460,23 @@ void CppPreprocessor::addDefinesInFile(const QString &fileName) } } +void CppPreprocessor::preprocessBuffer() +{ + while (mIncludes.count() > 0) { + QString s; + do { + s = getNextPreprocessor(); + if (s.startsWith('#')) { + simplify(s); + if (!s.isEmpty()) { + handlePreprocessor(s); + } + } + } while (!s.isEmpty()); + closeInclude(); + } +} + bool CppPreprocessor::isWordChar(const QChar &ch) { if (ch=='_' || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9')) { diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index 43768826..1258f5d4 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -70,6 +70,7 @@ private: PFileIncludes getFileIncludesEntry(const QString& FileName); void addDefinesInFile(const QString& fileName); + void preprocessBuffer(); /* * '_','a'..'z','A'..'Z','0'..'9' */ @@ -142,8 +143,8 @@ private: QHash mFileDefines; //dictionary to save defines for each headerfile; QList mIncludes; // stack of files we've stepped into. last one is current file, first one is source file QList mBranchResults;// stack of branch results (boolean). last one is current branch, first one is outermost branch - std::shared_ptr mIncludePaths; // path to include folders - std::shared_ptr mProjectIncludePaths; + QStringList mIncludePaths; // path to include folders + QStringList mProjectIncludePaths; bool mParseSystem; bool mParseLocal; QSet mScannedFiles; diff --git a/RedPandaIDE/parser/utils.cpp b/RedPandaIDE/parser/utils.cpp index c4477879..8c2a2367 100644 --- a/RedPandaIDE/parser/utils.cpp +++ b/RedPandaIDE/parser/utils.cpp @@ -239,7 +239,7 @@ void initParser() } QString getHeaderFileName(const QString &relativeTo, const QString &line, - std::shared_ptrincludePaths, std::shared_ptr projectIncludePaths) { + const QStringList& includePaths, const QStringList& projectIncludePaths) { QString result = ""; // Handle <> @@ -285,13 +285,11 @@ QString getLocalHeaderFileName(const QString &relativeTo, const QString &fileNam return ""; } -QString getSystemHeaderFileName(const QString &fileName, std::shared_ptr includePaths) +QString getSystemHeaderFileName(const QString &fileName, const QStringList& includePaths) { - if (!includePaths) - return ""; // Search compiler include directories - for (QString path:*includePaths) { + for (QString path:includePaths) { QDir dir(path); if (dir.exists(fileName)) return dir.absoluteFilePath(fileName); diff --git a/RedPandaIDE/parser/utils.h b/RedPandaIDE/parser/utils.h index 5f5a77bd..c0c70f53 100644 --- a/RedPandaIDE/parser/utils.h +++ b/RedPandaIDE/parser/utils.h @@ -164,9 +164,9 @@ extern QSet STLElementMethods; void initParser(); QString getHeaderFileName(const QString& relativeTo, const QString& line, - std::shared_ptr includePaths, std::shared_ptr projectIncludePaths); + const QStringList& includePaths, const QStringList& projectIncludePaths); QString getLocalHeaderFileName(const QString& relativeTo, const QString& fileName); -QString getSystemHeaderFileName(const QString& fileName, std::shared_ptr includePaths); +QString getSystemHeaderFileName(const QString& fileName, const QStringList& includePaths); #endif // PARSER_UTILS_H diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index 5872c37e..336a5e9b 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -452,3 +452,40 @@ QString changeFileExt(const QString& filename, const QString& ext) return filename.mid(0,filename.length()-suffix.length()-1)+"."+ext; } } + +QStringList ReadFileToLines(const QString &fileName) +{ + QFile file(fileName); + if (file.size()<=0) + return QStringList(); + QTextCodec* codec = QTextCodec::codecForLocale(); + QStringList result; + QTextCodec::ConverterState state; + bool ok = true; + if (file.open(QFile::ReadOnly)) { + while (!file.atEnd()) { + QByteArray array = file.readLine(); + QString s = codec->toUnicode(array,array.length(),&state); + if (state.invalidChars>0) { + ok=false; + break; + } + result.append(s); + } + if (!ok) { + file.seek(0); + result.clear(); + codec = QTextCodec::codecForName("UTF-8"); + while (!file.atEnd()) { + QByteArray array = file.readLine(); + QString s = codec->toUnicode(array,array.length(),&state); + if (state.invalidChars>0) { + result.clear(); + break; + } + result.append(s); + } + } + } + return result; +} diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index 8803c706..0faaceab 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -91,6 +91,7 @@ QStringList TextToLines(const QString& text); void TextToLines(const QString& text, LineProcessFunc lineFunc); QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec); +QStringList ReadFileToLines(const QString& fileName); void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc); void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers);