work save
This commit is contained in:
parent
5ee6988acc
commit
00da3303ac
|
@ -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')) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue