2021-08-14 22:52:37 +08:00
|
|
|
#ifndef CPPPARSER_H
|
|
|
|
#define CPPPARSER_H
|
|
|
|
|
2021-08-15 04:31:57 +08:00
|
|
|
#include <QMutex>
|
2021-08-14 22:52:37 +08:00
|
|
|
#include <QObject>
|
|
|
|
#include "statementmodel.h"
|
|
|
|
#include "cpptokenizer.h"
|
|
|
|
#include "cpppreprocessor.h"
|
|
|
|
|
|
|
|
class CppParser : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
2021-08-15 04:31:57 +08:00
|
|
|
|
|
|
|
using GetFileStreamCallBack = std::function<bool (const QString&, QStringList&)>;
|
2021-08-14 22:52:37 +08:00
|
|
|
public:
|
|
|
|
explicit CppParser(QObject *parent = nullptr);
|
2021-08-20 01:06:10 +08:00
|
|
|
~CppParser();
|
2021-08-14 22:52:37 +08:00
|
|
|
|
2021-08-20 01:06:10 +08:00
|
|
|
void addHardDefineByLine(const QString& line);
|
|
|
|
void addFileToScan(QString value, bool inProject = false);
|
|
|
|
void addIncludePath(const QString& value);
|
|
|
|
void addProjectIncludePath(const QString& value);
|
|
|
|
void clearIncludePaths();
|
|
|
|
void clearProjectIncludePaths();
|
|
|
|
void clearProjectFiles();
|
2021-08-15 04:31:57 +08:00
|
|
|
void parseHardDefines();
|
2021-08-15 16:49:37 +08:00
|
|
|
PFileIncludes findFileIncludes(const QString &filename, bool deleteIt = false);
|
|
|
|
void invalidateFile(const QString& fileName);
|
|
|
|
QStringList getFileDirectIncludes(const QString& filename) const;
|
|
|
|
const QList<QString>& getFileIncludes(const QString& filename) const;
|
|
|
|
const QSet<QString>& getFileUsings(const QString& filename) &;
|
2021-08-15 04:31:57 +08:00
|
|
|
|
2021-08-15 16:49:37 +08:00
|
|
|
bool isSystemHeaderFile(const QString& fileName);
|
|
|
|
bool isProjectHeaderFile(const QString& fileName);
|
|
|
|
void getSourcePair(const QString& fName, QString& CFile, QString& HFile);
|
|
|
|
void getClassesList(QStringList& list);
|
|
|
|
int suggestMemberInsertionLine(PStatement parentStatement,
|
|
|
|
StatementClassScope Scope,
|
|
|
|
bool addScopeStr);
|
|
|
|
// {
|
|
|
|
// function GetSystemHeaderFileName(const FileName: AnsiString): AnsiString; // <file.h>
|
|
|
|
// function GetProjectHeaderFileName(const FileName: AnsiString): AnsiString; // <file.h>
|
|
|
|
// function GetLocalHeaderFileName(const RelativeTo, FileName: AnsiString): AnsiString; // "file.h"
|
|
|
|
// }
|
|
|
|
QString getHeaderFileName(const QString& relativeTo, const QString& line) const;// both
|
|
|
|
bool isIncludeLine(const QString &line);
|
|
|
|
void parseFileList(bool updateView = true);
|
|
|
|
void parseFile(const QString& fileName, bool inProject,
|
|
|
|
bool onlyIfNotParsed = false, bool updateView = true);
|
|
|
|
QString statementKindStr(StatementKind value);
|
|
|
|
QString statementClassScopeStr(StatementClassScope value);
|
|
|
|
void reset();
|
2021-08-20 01:06:10 +08:00
|
|
|
|
2021-08-15 16:49:37 +08:00
|
|
|
QString prettyPrintStatement(PStatement statement, int line = -1);
|
|
|
|
void fillListOfFunctions(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
int line,
|
|
|
|
QStringList& list);
|
|
|
|
PStatement findAndScanBlockAt(const QString& filename, int line);
|
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
int line);
|
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
PStatement currentClass,
|
|
|
|
PStatement& currentClassType,
|
|
|
|
bool force = false);
|
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
PStatement currentClass,
|
|
|
|
bool force = false);
|
2021-08-15 04:31:57 +08:00
|
|
|
|
2021-08-15 16:49:37 +08:00
|
|
|
StatementKind findKindOfStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
int line);
|
|
|
|
QString getHintFromStatement(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
int line);
|
|
|
|
//{Find statement starting from startScope}
|
|
|
|
PStatement findStatementStartingFrom(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
PStatement startScope,
|
|
|
|
bool force = false);
|
|
|
|
PStatement findTypeDefinitionOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
PStatement currentClass);
|
|
|
|
QString FindFirstTemplateParamOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
PStatement currentClass);
|
|
|
|
int findLastOperator(const QString& phrase) const;
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatementList findNamespace(const QString& name); // return a list of PSTATEMENTS (of the namespace)
|
2021-08-15 16:49:37 +08:00
|
|
|
bool freeze(); // Freeze/Lock (stop reparse while searching)
|
|
|
|
bool freeze(const QString& serialId); // Freeze/Lock (stop reparse while searching)
|
|
|
|
void unFreeze(); // UnFree/UnLock (reparse while searching)
|
|
|
|
bool getParsing();
|
2021-08-15 04:31:57 +08:00
|
|
|
|
2021-08-15 16:49:37 +08:00
|
|
|
QString findFunctionDoc(const QString& fileName,
|
|
|
|
int line,
|
|
|
|
QStringList& params,
|
|
|
|
bool &isVoid);
|
2021-08-14 22:52:37 +08:00
|
|
|
signals:
|
2021-08-19 23:49:23 +08:00
|
|
|
void onProgress(const QString& fileName, int total, int current);
|
|
|
|
void onBusy();
|
|
|
|
void onStartParsing();
|
|
|
|
void onEndParsing(int total, int updateView);
|
2021-08-15 04:31:57 +08:00
|
|
|
private:
|
|
|
|
PStatement addInheritedStatement(
|
|
|
|
PStatement derived,
|
|
|
|
PStatement inherit,
|
|
|
|
StatementClassScope access);
|
|
|
|
|
|
|
|
PStatement addChildStatement(
|
|
|
|
// support for multiple parents (only typedef struct/union use multiple parents)
|
2021-08-15 16:49:37 +08:00
|
|
|
PStatement parent,
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QString& hintText,
|
|
|
|
const QString& aType, // "Type" is already in use
|
|
|
|
const QString& command,
|
|
|
|
const QString& args,
|
|
|
|
const QString& value,
|
|
|
|
int line,
|
|
|
|
StatementKind kind,
|
|
|
|
StatementScope scope,
|
|
|
|
StatementClassScope classScope,
|
|
|
|
bool isDefinition,
|
|
|
|
bool isStatic); // TODO: InheritanceList not supported
|
|
|
|
PStatement addStatement(
|
|
|
|
PStatement parent,
|
|
|
|
const QString &fileName,
|
|
|
|
const QString &hintText,
|
|
|
|
const QString &aType, // "Type" is already in use
|
|
|
|
const QString &command,
|
|
|
|
const QString &args,
|
|
|
|
const QString& value,
|
|
|
|
int line,
|
|
|
|
StatementKind kind,
|
|
|
|
StatementScope scope,
|
|
|
|
StatementClassScope classScope,
|
|
|
|
bool isDefinition,
|
|
|
|
bool isStatic);
|
|
|
|
void setInheritance(int index, PStatement classStatement, bool isStruct);
|
2021-08-19 23:49:23 +08:00
|
|
|
bool isCurrentScope(const QString& command);
|
2021-08-15 04:31:57 +08:00
|
|
|
void addSoloScopeLevel(PStatement statement, int line); // adds new solo level
|
|
|
|
void removeScopeLevel(int line); // removes level
|
|
|
|
int skipBraces(int startAt);
|
|
|
|
int skipBracket(int startAt);
|
2021-08-15 16:49:37 +08:00
|
|
|
bool checkForCatchBlock();
|
|
|
|
bool checkForEnum();
|
|
|
|
bool checkForForBlock();
|
2021-08-15 04:31:57 +08:00
|
|
|
bool checkForKeyword();
|
2021-08-15 16:49:37 +08:00
|
|
|
bool checkForMethod(QString &sType, QString &sName, QString &sArgs,
|
|
|
|
bool &isStatic, bool &isFriend); // caching of results
|
2021-08-15 04:31:57 +08:00
|
|
|
bool checkForNamespace();
|
2021-08-15 16:49:37 +08:00
|
|
|
bool checkForPreprocessor();
|
|
|
|
bool checkForScope();
|
2021-08-15 20:25:54 +08:00
|
|
|
void checkForSkipStatement();
|
2021-08-19 12:01:01 +08:00
|
|
|
bool checkForStructs();
|
2021-08-15 04:31:57 +08:00
|
|
|
bool checkForTypedef();
|
|
|
|
bool checkForTypedefEnum();
|
|
|
|
bool checkForTypedefStruct();
|
2021-08-15 17:52:39 +08:00
|
|
|
bool checkForUsing();
|
2021-08-15 04:31:57 +08:00
|
|
|
bool checkForVar();
|
2021-08-16 00:47:35 +08:00
|
|
|
QString expandMacroType(const QString& name);
|
|
|
|
//{procedure ResetDefines;}
|
|
|
|
PStatement findMemberOfStatement(
|
|
|
|
const QString& phrase,
|
|
|
|
PStatement scopeStatement);
|
|
|
|
PStatement findStatementInScope(
|
|
|
|
const QString& name,
|
|
|
|
const QString& noNameArgs,
|
|
|
|
StatementKind kind,
|
|
|
|
PStatement scope);
|
2021-08-19 23:49:23 +08:00
|
|
|
StatementClassScope getClassScope(int index);
|
2021-08-15 04:31:57 +08:00
|
|
|
int getCurrentBlockBeginSkip();
|
2021-08-16 00:47:35 +08:00
|
|
|
int getCurrentBlockEndSkip();
|
2021-08-15 04:31:57 +08:00
|
|
|
int getCurrentInlineNamespaceEndSkip();
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement getCurrentScope(); // gets last item from last level
|
|
|
|
void getFullNameSpace(
|
|
|
|
const QString& phrase,
|
|
|
|
QString& sNamespace,
|
|
|
|
QString& member);
|
2021-08-17 23:30:14 +08:00
|
|
|
QString getFullStatementName(
|
|
|
|
const QString& command,
|
|
|
|
PStatement parent);
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement getIncompleteClass(
|
|
|
|
const QString& command,
|
|
|
|
PStatement parentScope);
|
|
|
|
StatementScope getScope();
|
2021-08-17 23:30:14 +08:00
|
|
|
QString getStatementKey(const QString& sName,
|
|
|
|
const QString& sType,
|
|
|
|
const QString& sNoNameArgs);
|
|
|
|
void handleCatchBlock();
|
|
|
|
void handleEnum();
|
|
|
|
void handleForBlock();
|
2021-08-18 17:02:57 +08:00
|
|
|
void handleKeyword();
|
2021-08-19 12:01:01 +08:00
|
|
|
void handleMethod(
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString& sType,
|
|
|
|
const QString& sName,
|
|
|
|
const QString& sArgs,
|
|
|
|
bool isStatic,
|
|
|
|
bool isFriend);
|
|
|
|
void handleNamespace();
|
2021-08-17 23:30:14 +08:00
|
|
|
void handleOtherTypedefs();
|
|
|
|
void handlePreprocessor();
|
|
|
|
void handleScope();
|
2021-08-15 04:31:57 +08:00
|
|
|
bool handleStatement();
|
2021-08-17 23:30:14 +08:00
|
|
|
void handleStructs(bool isTypedef = false);
|
|
|
|
void handleUsing();
|
|
|
|
void handleVar();
|
2021-08-19 23:49:23 +08:00
|
|
|
void internalParse(const QString& fileName);
|
2021-08-15 04:31:57 +08:00
|
|
|
// function FindMacroDefine(const Command: AnsiString): PStatement;
|
|
|
|
void inheritClassStatement(
|
|
|
|
PStatement derived,
|
|
|
|
bool isStruct,
|
|
|
|
PStatement base,
|
|
|
|
StatementClassScope access);
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement doFindStatementInScope(const QString& name,
|
|
|
|
const QString& noNameArgs,
|
|
|
|
StatementKind kind,
|
|
|
|
PStatement scope);
|
2021-08-15 04:31:57 +08:00
|
|
|
void internalInvalidateFile(const QString& fileName);
|
|
|
|
void internalInvalidateFiles(const QStringList& files);
|
|
|
|
void calculateFilesToBeReparsed(const QString& fileName,
|
|
|
|
QStringList& files);
|
2021-08-16 00:47:35 +08:00
|
|
|
int calcKeyLenForStruct(const QString& word);
|
2021-08-15 04:31:57 +08:00
|
|
|
// {
|
|
|
|
// function GetClass(const Phrase: AnsiString): AnsiString;
|
|
|
|
// function GetMember(const Phrase: AnsiString): AnsiString;
|
|
|
|
// function GetOperator(const Phrase: AnsiString): AnsiString;
|
|
|
|
// function GetRemainder(const Phrase: AnsiString): AnsiString;
|
|
|
|
// }
|
2021-08-17 23:30:14 +08:00
|
|
|
void scanMethodArgs(
|
|
|
|
PStatement functionStatement,
|
|
|
|
const QString& argStr);
|
2021-08-15 04:31:57 +08:00
|
|
|
QString splitPhrase(const QString& phrase, QString& sClazz, QString &sMember,
|
|
|
|
QString& sOperator);
|
2021-08-15 16:49:37 +08:00
|
|
|
|
|
|
|
QString removeArgNames(const QString& args);
|
2021-08-15 17:52:39 +08:00
|
|
|
|
|
|
|
bool isSpaceChar(const QChar& ch);
|
|
|
|
|
2021-08-15 20:25:54 +08:00
|
|
|
bool isWordChar(const QChar& ch);
|
|
|
|
|
2021-08-15 17:52:39 +08:00
|
|
|
bool isLetterChar(const QChar& ch);
|
|
|
|
|
|
|
|
bool isDigitChar(const QChar& ch);
|
|
|
|
|
|
|
|
/*'(', ';', ':', '{', '}', '#' */
|
|
|
|
bool isSeperator(const QChar& ch);
|
|
|
|
|
2021-08-18 05:34:04 +08:00
|
|
|
/*';', '{', '}'*/
|
|
|
|
bool isblockChar(const QChar& ch);
|
|
|
|
|
2021-08-16 00:47:35 +08:00
|
|
|
/* '#', ',', ';', ':', '{', '}', '!', '/', '+', '-', '<', '>' */
|
|
|
|
bool isInvalidVarPrefixChar(const QChar& ch);
|
|
|
|
|
2021-08-18 17:02:57 +08:00
|
|
|
/*'{', '}' */
|
|
|
|
bool isBraceChar(const QChar& ch);
|
|
|
|
|
2021-08-15 20:25:54 +08:00
|
|
|
bool isLineChar(const QChar& ch);
|
|
|
|
|
|
|
|
bool isNotFuncArgs(const QString& args);
|
|
|
|
|
2021-08-17 23:30:14 +08:00
|
|
|
/**
|
|
|
|
* @brief Test if a statement is a class/struct/union/namespace/function
|
|
|
|
* @param kind
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
bool isNamedScope(StatementKind kind);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Test if a statement is a class/struct/union/enum/enum class/typedef
|
|
|
|
* @param kind
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
bool isTypeStatement(StatementKind kind);
|
|
|
|
|
2021-08-15 04:31:57 +08:00
|
|
|
void updateSerialId();
|
2021-08-17 23:30:14 +08:00
|
|
|
|
|
|
|
|
2021-08-14 22:52:37 +08:00
|
|
|
private:
|
|
|
|
int mParserId;
|
|
|
|
int mSerialCount;
|
2021-08-19 23:49:23 +08:00
|
|
|
QString mSerialId;
|
2021-08-14 22:52:37 +08:00
|
|
|
int mUniqId;
|
|
|
|
bool mEnabled;
|
|
|
|
int mIndex;
|
|
|
|
bool mIsHeader;
|
|
|
|
bool mIsSystemHeader;
|
|
|
|
QString mCurrentFile;
|
|
|
|
// stack list , each element is a list of one/many scopes(like intypedef struct s1,s2;
|
|
|
|
// It's used for store scope nesting infos
|
|
|
|
QVector<PStatement> mCurrentScope;
|
|
|
|
QVector<StatementClassScope> mCurrentClassScope;
|
|
|
|
|
|
|
|
// the start index in tokens to skip to ; when parsing typedef struct we need to skip
|
|
|
|
// the names after the closing bracket because we have processed it
|
|
|
|
QVector<int> mSkipList; // TList<Integer>
|
|
|
|
StatementClassScope mClassScope;
|
|
|
|
StatementModel mStatementList;
|
|
|
|
std::shared_ptr<QHash<QString,PFileIncludes>> mIncludesList; //List of scaned files and it's infos
|
|
|
|
//It's used in preprocessor, so we can't use fIncludeList instead
|
|
|
|
std::shared_ptr<QSet<QString>> mScannedFiles; // List of scaned file names
|
|
|
|
CppTokenizer mTokenizer;
|
|
|
|
CppPreprocessor mPreprocessor;
|
2021-08-15 04:31:57 +08:00
|
|
|
//{ List of current compiler set's include path}
|
2021-08-19 23:49:23 +08:00
|
|
|
QSet<QString> mIncludePaths;
|
2021-08-15 04:31:57 +08:00
|
|
|
//{ List of current project's include path }
|
2021-08-19 23:49:23 +08:00
|
|
|
QSet<QString> mProjectIncludePaths;
|
2021-08-15 04:31:57 +08:00
|
|
|
//{ List of current project's include path }
|
|
|
|
QSet<QString> mProjectFiles;
|
|
|
|
QVector<int> mBlockBeginSkips; //list of for/catch block begin token index;
|
|
|
|
QVector<int> mBlockEndSkips; //list of for/catch block end token index;
|
|
|
|
QVector<int> mInlineNamespaceEndSkips; // list for inline namespace end token index;
|
2021-08-19 23:49:23 +08:00
|
|
|
QSet<QString> mFilesToScan; // list of base files to scan
|
2021-08-15 04:31:57 +08:00
|
|
|
int mFilesScannedCount; // count of files that have been scanned
|
|
|
|
int mFilesToScanCount; // count of files and files included in files that have to be scanned
|
|
|
|
bool mParseLocalHeaders;
|
|
|
|
bool mParseGlobalHeaders;
|
|
|
|
bool mIsProjectFile;
|
2021-08-14 22:52:37 +08:00
|
|
|
//fMacroDefines : TList;
|
2021-08-15 04:31:57 +08:00
|
|
|
int mLockCount; // lock(don't reparse) when we need to find statements in a batch
|
|
|
|
bool mParsing;
|
|
|
|
QHash<QString,PStatementList> mNamespaces; //TStringList<String,List<Statement>> namespace and the statements in its scope
|
2021-08-14 22:52:37 +08:00
|
|
|
//fRemovedStatements: THashedStringList; //THashedStringList<String,PRemovedStatements>
|
2021-08-15 04:31:57 +08:00
|
|
|
|
2021-08-19 23:49:23 +08:00
|
|
|
QRecursiveMutex mMutex;
|
2021-08-15 04:31:57 +08:00
|
|
|
GetFileStreamCallBack mOnGetFileStream;
|
2021-08-14 22:52:37 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // CPPPARSER_H
|