work save

This commit is contained in:
royqh1979@gmail.com 2021-08-11 20:06:28 +08:00
parent 5ee6988acc
commit 00da3303ac
6 changed files with 175 additions and 9 deletions

View File

@ -1,6 +1,8 @@
#include "cpppreprocessor.h"
#include "../utils.h"
#include <QTextCodec>
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>();
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<FileIncludes>();
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;i<mBuffer.count();i++) {
mBuffer[i] = mBuffer[i].trimmed();
}
// Update result file
QString includeLine = "#include " + fileName + ":1";
if (mIncludes.count()>1) { // 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')) {

View File

@ -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<QString, PDefineMap> mFileDefines; //dictionary to save defines for each headerfile;
QList<PParsedFile> mIncludes; // stack of files we've stepped into. last one is current file, first one is source file
QList<bool> mBranchResults;// stack of branch results (boolean). last one is current branch, first one is outermost branch
std::shared_ptr<QStringList> mIncludePaths; // path to include folders
std::shared_ptr<QStringList> mProjectIncludePaths;
QStringList mIncludePaths; // path to include folders
QStringList mProjectIncludePaths;
bool mParseSystem;
bool mParseLocal;
QSet<QString> mScannedFiles;

View File

@ -239,7 +239,7 @@ void initParser()
}
QString getHeaderFileName(const QString &relativeTo, const QString &line,
std::shared_ptr<QStringList>includePaths, std::shared_ptr<QStringList> 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<QStringList> 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);

View File

@ -164,9 +164,9 @@ extern QSet<QString> STLElementMethods;
void initParser();
QString getHeaderFileName(const QString& relativeTo, const QString& line,
std::shared_ptr<QStringList> includePaths, std::shared_ptr<QStringList> projectIncludePaths);
const QStringList& includePaths, const QStringList& projectIncludePaths);
QString getLocalHeaderFileName(const QString& relativeTo, const QString& fileName);
QString getSystemHeaderFileName(const QString& fileName, std::shared_ptr<QStringList> includePaths);
QString getSystemHeaderFileName(const QString& fileName, const QStringList& includePaths);
#endif // PARSER_UTILS_H

View File

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

View File

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