2021-12-26 23:18:28 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
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>
|
2021-08-23 10:16:06 +08:00
|
|
|
#include <QThread>
|
2022-01-04 16:50:54 +08:00
|
|
|
#include <QVector>
|
2021-08-14 22:52:37 +08:00
|
|
|
#include "statementmodel.h"
|
|
|
|
#include "cpptokenizer.h"
|
|
|
|
#include "cpppreprocessor.h"
|
|
|
|
|
|
|
|
class CppParser : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
2021-08-15 04:31:57 +08:00
|
|
|
|
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);
|
2022-11-07 11:24:23 +08:00
|
|
|
void addProjectFile(const QString &fileName, bool needScan);
|
2021-08-20 01:06:10 +08:00
|
|
|
void addIncludePath(const QString& value);
|
2022-11-06 22:51:14 +08:00
|
|
|
void removeProjectFile(const QString& value);
|
2021-08-20 01:06:10 +08:00
|
|
|
void addProjectIncludePath(const QString& value);
|
|
|
|
void clearIncludePaths();
|
|
|
|
void clearProjectIncludePaths();
|
|
|
|
void clearProjectFiles();
|
2021-09-24 18:02:42 +08:00
|
|
|
QList<PStatement> getListOfFunctions(const QString& fileName,
|
2021-08-22 16:08:46 +08:00
|
|
|
const QString& phrase,
|
2021-09-24 18:02:42 +08:00
|
|
|
int line);
|
2022-11-10 08:05:04 +08:00
|
|
|
PStatement findScopeStatement(const QString& filename, int line);
|
2022-03-23 14:13:10 +08:00
|
|
|
PFileIncludes findFileIncludes(const QString &filename, bool deleteIt = false);
|
2021-08-22 16:08:46 +08:00
|
|
|
QString findFirstTemplateParamOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& currentScope);
|
2021-08-22 16:08:46 +08:00
|
|
|
PStatement findFunctionAt(const QString& fileName,
|
|
|
|
int line);
|
|
|
|
int findLastOperator(const QString& phrase) const;
|
|
|
|
PStatementList findNamespace(const QString& name); // return a list of PSTATEMENTS (of the namespace)
|
2021-11-05 10:44:23 +08:00
|
|
|
PStatement findStatement(const QString& fullname);
|
2021-08-22 16:08:46 +08:00
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
int line);
|
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& currentScope,
|
2021-08-25 00:20:07 +08:00
|
|
|
PStatement& parentScopeType,
|
2021-08-22 16:08:46 +08:00
|
|
|
bool force = false);
|
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& currentClass,
|
2021-08-22 16:08:46 +08:00
|
|
|
bool force = false);
|
2021-12-18 23:36:58 +08:00
|
|
|
|
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QStringList& expression,
|
|
|
|
const PStatement& currentScope);
|
2021-12-19 10:16:46 +08:00
|
|
|
PStatement findStatementOf(const QString& fileName,
|
|
|
|
const QStringList& expression,
|
|
|
|
int line);
|
2022-03-15 21:33:27 +08:00
|
|
|
PStatement findAliasedStatement(const PStatement& statement);
|
2021-12-19 10:16:46 +08:00
|
|
|
|
2021-12-06 09:02:39 +08:00
|
|
|
/**
|
|
|
|
* @brief evaluate the expression
|
|
|
|
* @param fileName
|
|
|
|
* @param expression
|
|
|
|
* @param currentScope
|
|
|
|
* @return the statement of the evaluation result
|
|
|
|
*/
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement evalExpression(const QString& fileName,
|
2021-12-06 09:02:39 +08:00
|
|
|
const QStringList& expression,
|
2021-12-04 18:38:54 +08:00
|
|
|
const PStatement& currentScope);
|
2021-08-22 21:23:58 +08:00
|
|
|
PStatement findTypeDefinitionOf(const QString& fileName,
|
|
|
|
const QString& aType,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& currentClass);
|
2022-01-26 12:17:15 +08:00
|
|
|
PStatement findTypeDef(const PStatement& statement,
|
|
|
|
const QString& fileName);
|
2021-08-22 21:23:58 +08:00
|
|
|
bool freeze(); // Freeze/Lock (stop reparse while searching)
|
|
|
|
bool freeze(const QString& serialId); // Freeze/Lock (stop reparse while searching)
|
|
|
|
QStringList getClassesList();
|
2022-06-04 14:44:50 +08:00
|
|
|
QStringList getFileDirectIncludes(const QString& filename);
|
2021-08-22 21:23:58 +08:00
|
|
|
QSet<QString> getFileIncludes(const QString& filename);
|
|
|
|
QSet<QString> getFileUsings(const QString& filename);
|
2021-08-22 16:08:46 +08:00
|
|
|
|
2022-10-18 12:24:59 +08:00
|
|
|
QString getHeaderFileName(const QString& relativeTo, const QString& headerName, bool fromNext=false);// both
|
2022-01-27 20:31:44 +08:00
|
|
|
|
2021-08-15 16:49:37 +08:00
|
|
|
void invalidateFile(const QString& fileName);
|
2021-08-22 23:48:00 +08:00
|
|
|
bool isIncludeLine(const QString &line);
|
2022-10-18 12:24:59 +08:00
|
|
|
bool isIncludeNextLine(const QString &line);
|
2021-08-15 16:49:37 +08:00
|
|
|
bool isProjectHeaderFile(const QString& fileName);
|
2021-08-22 21:23:58 +08:00
|
|
|
bool isSystemHeaderFile(const QString& fileName);
|
|
|
|
void parseFile(const QString& fileName, bool inProject,
|
|
|
|
bool onlyIfNotParsed = false, bool updateView = true);
|
|
|
|
void parseFileList(bool updateView = true);
|
|
|
|
void parseHardDefines();
|
2021-08-22 23:48:00 +08:00
|
|
|
bool parsing() const;
|
2022-10-18 12:24:59 +08:00
|
|
|
void resetParser();
|
2021-08-22 23:48:00 +08:00
|
|
|
void unFreeze(); // UnFree/UnLock (reparse while searching)
|
2021-09-13 22:45:50 +08:00
|
|
|
QSet<QString> scannedFiles();
|
2021-08-22 21:23:58 +08:00
|
|
|
|
2022-08-24 17:05:16 +08:00
|
|
|
bool isFileParsed(const QString& filename);
|
|
|
|
|
2021-08-29 17:23:40 +08:00
|
|
|
QString prettyPrintStatement(const PStatement& statement, const QString& filename, int line = -1);
|
2021-08-22 05:50:26 +08:00
|
|
|
|
2021-08-21 22:15:44 +08:00
|
|
|
bool enabled() const;
|
|
|
|
void setEnabled(bool newEnabled);
|
|
|
|
|
|
|
|
const QSet<QString> &filesToScan() const;
|
|
|
|
void setFilesToScan(const QSet<QString> &newFilesToScan);
|
|
|
|
|
2021-08-22 21:23:58 +08:00
|
|
|
void setOnGetFileStream(const GetFileStreamCallBack &newOnGetFileStream);
|
|
|
|
|
2021-08-22 23:48:00 +08:00
|
|
|
int parserId() const;
|
|
|
|
|
2021-08-23 03:47:28 +08:00
|
|
|
const QString &serialId() const;
|
|
|
|
|
2021-08-23 10:16:06 +08:00
|
|
|
bool parseLocalHeaders() const;
|
|
|
|
void setParseLocalHeaders(bool newParseLocalHeaders);
|
|
|
|
|
|
|
|
bool parseGlobalHeaders() const;
|
|
|
|
void setParseGlobalHeaders(bool newParseGlobalHeaders);
|
|
|
|
|
2021-08-29 00:48:23 +08:00
|
|
|
const QSet<QString>& includePaths();
|
|
|
|
const QSet<QString>& projectIncludePaths();
|
|
|
|
|
2021-08-24 15:05:10 +08:00
|
|
|
const StatementModel &statementList() const;
|
|
|
|
|
2022-07-28 13:51:38 +08:00
|
|
|
ParserLanguage language() const;
|
|
|
|
void setLanguage(ParserLanguage newLanguage);
|
|
|
|
|
2022-11-07 11:24:23 +08:00
|
|
|
const QSet<QString> &projectFiles() const;
|
|
|
|
|
2022-11-27 13:32:14 +08:00
|
|
|
QList<QString> namespaces();
|
|
|
|
|
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(
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& derived,
|
|
|
|
const PStatement& inherit,
|
2021-08-15 04:31:57 +08:00
|
|
|
StatementClassScope access);
|
|
|
|
|
|
|
|
PStatement addChildStatement(
|
|
|
|
// support for multiple parents (only typedef struct/union use multiple parents)
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& parent,
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QString& aType, // "Type" is already in use
|
|
|
|
const QString& command,
|
|
|
|
const QString& args,
|
2022-10-31 19:37:24 +08:00
|
|
|
const QString& noNameArgs,
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString& value,
|
|
|
|
int line,
|
|
|
|
StatementKind kind,
|
2021-08-29 00:48:23 +08:00
|
|
|
const StatementScope& scope,
|
|
|
|
const StatementClassScope& classScope,
|
2022-11-16 10:29:20 +08:00
|
|
|
StatementProperties properties); // TODO: InheritanceList not supported
|
2021-08-15 04:31:57 +08:00
|
|
|
PStatement addStatement(
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& parent,
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString &fileName,
|
|
|
|
const QString &aType, // "Type" is already in use
|
|
|
|
const QString &command,
|
|
|
|
const QString &args,
|
2022-10-31 19:37:24 +08:00
|
|
|
const QString &noNameArgs,
|
|
|
|
const QString& value,
|
|
|
|
int line,
|
|
|
|
StatementKind kind,
|
|
|
|
const StatementScope& scope,
|
|
|
|
const StatementClassScope& classScope,
|
2022-11-16 10:29:20 +08:00
|
|
|
StatementProperties properties);
|
2022-10-31 19:37:24 +08:00
|
|
|
PStatement addStatement(
|
|
|
|
const PStatement& parent,
|
|
|
|
const QString &fileName,
|
|
|
|
const QString &aType, // "Type" is already in use
|
|
|
|
const QString &command,
|
|
|
|
int argStart,
|
|
|
|
int argEnd,
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString& value,
|
|
|
|
int line,
|
|
|
|
StatementKind kind,
|
2021-08-29 00:48:23 +08:00
|
|
|
const StatementScope& scope,
|
|
|
|
const StatementClassScope& classScope,
|
2022-11-16 10:29:20 +08:00
|
|
|
StatementProperties properties);
|
2021-08-29 00:48:23 +08:00
|
|
|
void setInheritance(int index, const PStatement& classStatement, bool isStruct);
|
2021-08-19 23:49:23 +08:00
|
|
|
bool isCurrentScope(const QString& command);
|
2022-11-02 13:38:26 +08:00
|
|
|
void addSoloScopeLevel(PStatement& statement, int line, bool shouldResetBlock=false); // adds new solo level
|
2021-08-15 04:31:57 +08:00
|
|
|
void removeScopeLevel(int line); // removes level
|
2022-11-01 09:02:17 +08:00
|
|
|
|
|
|
|
int indexOfMatchingBrace(int startAt) {
|
2022-11-01 00:01:46 +08:00
|
|
|
return mTokenizer[startAt]->matchIndex;
|
|
|
|
}
|
2021-11-12 07:26:13 +08:00
|
|
|
|
|
|
|
void internalClear();
|
|
|
|
|
2022-10-22 19:33:20 +08:00
|
|
|
QStringList sortFilesByIncludeRelations(const QSet<QString> &files);
|
|
|
|
|
2022-11-01 09:02:17 +08:00
|
|
|
bool checkForKeyword(KeywordType &keywordType);
|
2022-10-31 19:37:24 +08:00
|
|
|
bool checkForMethod(QString &sType, QString &sName, int &argStartIndex,
|
|
|
|
int &argEndIndex, bool &isStatic, bool &isFriend); // caching of results
|
2022-11-01 09:02:17 +08:00
|
|
|
bool checkForNamespace(KeywordType keywordType);
|
2021-08-15 16:49:37 +08:00
|
|
|
bool checkForPreprocessor();
|
2022-11-04 20:27:35 +08:00
|
|
|
// bool checkForLambda();
|
2022-11-01 09:02:17 +08:00
|
|
|
bool checkForScope(KeywordType keywordType);
|
|
|
|
bool checkForStructs(KeywordType keywordType);
|
2021-08-15 04:31:57 +08:00
|
|
|
bool checkForTypedefEnum();
|
|
|
|
bool checkForTypedefStruct();
|
2022-11-01 09:02:17 +08:00
|
|
|
bool checkForUsing(KeywordType keywordType);
|
2022-10-22 10:44:10 +08:00
|
|
|
|
2022-11-04 23:44:11 +08:00
|
|
|
void checkAndHandleMethodOrVar(KeywordType keywordType);
|
2022-11-04 20:27:35 +08:00
|
|
|
|
2022-11-27 13:32:14 +08:00
|
|
|
QString doFindFirstTemplateParamOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
const PStatement& currentScope);
|
2022-11-29 16:48:40 +08:00
|
|
|
QString doFindTemplateParamOf(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
int index,
|
|
|
|
const PStatement& currentScope);
|
2022-11-27 13:32:14 +08:00
|
|
|
|
2021-08-29 00:48:23 +08:00
|
|
|
void fillListOfFunctions(const QString& fileName, int line,
|
|
|
|
const PStatement& statement,
|
|
|
|
const PStatement& scopeStatement, QStringList& list);
|
2021-09-24 18:02:42 +08:00
|
|
|
QList<PStatement> getListOfFunctions(const QString& fileName, int line,
|
|
|
|
const PStatement& statement,
|
|
|
|
const PStatement& scopeStatement);
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement findMemberOfStatement(
|
|
|
|
const QString& phrase,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& scopeStatement);
|
2022-03-16 16:24:39 +08:00
|
|
|
QList<PStatement> findMembersOfStatement(const QString& phrase,
|
|
|
|
const PStatement& scopeStatement);
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement findStatementInScope(
|
|
|
|
const QString& name,
|
|
|
|
const QString& noNameArgs,
|
|
|
|
StatementKind kind,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& scope);
|
2021-08-22 21:23:58 +08:00
|
|
|
PStatement findStatementInScope(
|
|
|
|
const QString& name,
|
2022-03-23 14:13:10 +08:00
|
|
|
const PStatement& scope);
|
2021-08-22 21:23:58 +08:00
|
|
|
PStatement findStatementInNamespace(
|
|
|
|
const QString& name,
|
|
|
|
const QString& namespaceName);
|
2021-12-04 18:38:54 +08:00
|
|
|
|
2021-12-07 08:23:27 +08:00
|
|
|
//{Find statement starting from startScope}
|
|
|
|
PStatement findStatementStartingFrom(const QString& fileName,
|
|
|
|
const QString& phrase,
|
|
|
|
const PStatement& startScope);
|
|
|
|
|
2021-12-06 09:02:39 +08:00
|
|
|
/**
|
|
|
|
* @brief evaluate the expression (starting from pos) in the scope
|
|
|
|
* @param fileName
|
|
|
|
* @param phraseExpression
|
|
|
|
* @param pos
|
|
|
|
* @param scope
|
|
|
|
* @param previousResult the result of evalution for expression from 0 to pos-1
|
|
|
|
* @param freeScoped if the expression left is
|
|
|
|
* @return
|
|
|
|
*/
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement doEvalExpression(const QString& fileName,
|
2021-12-06 09:02:39 +08:00
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
|
|
|
const PStatement& scope,
|
2021-12-06 11:37:37 +08:00
|
|
|
const PEvalStatement& previousResult,
|
2021-12-06 09:02:39 +08:00
|
|
|
bool freeScoped);
|
|
|
|
|
2021-12-08 19:55:15 +08:00
|
|
|
PEvalStatement doEvalPointerArithmetic(
|
|
|
|
const QString& fileName,
|
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
|
|
|
const PStatement& scope,
|
|
|
|
const PEvalStatement& previousResult,
|
|
|
|
bool freeScoped);
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement doEvalPointerToMembers(
|
2021-12-04 18:38:54 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
2021-12-06 09:02:39 +08:00
|
|
|
const PStatement& scope,
|
2021-12-06 11:37:37 +08:00
|
|
|
const PEvalStatement& previousResult,
|
2021-12-05 10:52:17 +08:00
|
|
|
bool freeScoped);
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement doEvalCCast(
|
2021-12-05 10:52:17 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
2021-12-06 09:02:39 +08:00
|
|
|
const PStatement& scope,
|
2021-12-06 11:37:37 +08:00
|
|
|
const PEvalStatement& previousResult,
|
2021-12-05 10:52:17 +08:00
|
|
|
bool freeScoped);
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement doEvalMemberAccess(
|
2021-12-05 10:52:17 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
2021-12-06 09:02:39 +08:00
|
|
|
const PStatement& scope,
|
2021-12-06 11:37:37 +08:00
|
|
|
const PEvalStatement& previousResult,
|
2021-12-05 10:52:17 +08:00
|
|
|
bool freeScoped);
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement doEvalScopeResolution(
|
2021-12-05 10:52:17 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
2021-12-06 09:02:39 +08:00
|
|
|
const PStatement& scope,
|
2021-12-06 11:37:37 +08:00
|
|
|
const PEvalStatement& previousResult,
|
2021-12-06 09:02:39 +08:00
|
|
|
bool freeScoped);
|
2021-12-06 11:37:37 +08:00
|
|
|
PEvalStatement doEvalTerm(
|
2021-12-06 09:02:39 +08:00
|
|
|
const QString& fileName,
|
|
|
|
const QStringList& phraseExpression,
|
|
|
|
int &pos,
|
|
|
|
const PStatement& scope,
|
2021-12-06 11:37:37 +08:00
|
|
|
const PEvalStatement& previousResult,
|
2021-12-05 10:52:17 +08:00
|
|
|
bool freeScoped);
|
2021-12-05 20:27:09 +08:00
|
|
|
|
2021-12-07 14:48:20 +08:00
|
|
|
PEvalStatement doCreateEvalNamespace(const PStatement& namespaceStatement);
|
2021-12-07 08:23:27 +08:00
|
|
|
|
2021-12-07 14:48:20 +08:00
|
|
|
PEvalStatement doCreateEvalType(const QString& fileName,const PStatement& typeStatement);
|
2021-12-08 19:13:47 +08:00
|
|
|
PEvalStatement doCreateEvalType(const QString& primitiveType);
|
2021-12-07 08:23:27 +08:00
|
|
|
|
2022-11-29 16:48:40 +08:00
|
|
|
PEvalStatement doCreateEvalVariable(
|
|
|
|
const QString& fileName,
|
|
|
|
const PStatement& varStatement,
|
|
|
|
const QString& baseTemplateParams,
|
|
|
|
const PStatement& scope);
|
|
|
|
PEvalStatement doCreateEvalFunction(const QString& fileName, const PStatement& funcStatement);
|
2021-12-08 19:13:47 +08:00
|
|
|
PEvalStatement doCreateEvalLiteral(const QString& type);
|
|
|
|
void doSkipInExpression(const QStringList& expression, int&pos, const QString& startSymbol, const QString& endSymbol);
|
2022-03-23 12:30:58 +08:00
|
|
|
|
|
|
|
bool isIdentifier(const QString& token) const {
|
2022-11-04 20:27:35 +08:00
|
|
|
return (!token.isEmpty() && isIdentChar(token.front())
|
2022-03-23 12:30:58 +08:00
|
|
|
&& !token.contains('\"'));
|
|
|
|
}
|
|
|
|
|
2022-11-01 22:10:54 +08:00
|
|
|
bool isIdentifierOrPointer(const QString& term) const {
|
|
|
|
switch(term[0].unicode()) {
|
|
|
|
case '*':
|
|
|
|
return true;
|
|
|
|
case '\"':
|
|
|
|
case '\'':
|
|
|
|
return false;
|
|
|
|
default:
|
2022-11-04 20:27:35 +08:00
|
|
|
return isIdentChar(term[0]);
|
2022-11-01 22:10:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isIntegerLiteral(const QString& token) const {
|
|
|
|
if (token.isEmpty())
|
|
|
|
return false;
|
|
|
|
QChar ch = token.front();
|
|
|
|
return (ch>='0' && ch<='9' && !token.contains(".") && !token.contains("e"));
|
|
|
|
}
|
|
|
|
bool isFloatLiteral(const QString& token) const {
|
|
|
|
if (token.isEmpty())
|
|
|
|
return false;
|
|
|
|
QChar ch = token.front();
|
|
|
|
return (ch>='0' && ch<='9' && (token.contains(".") || token.contains("e")));
|
|
|
|
}
|
|
|
|
bool isStringLiteral(const QString& token) const {
|
|
|
|
if (token.isEmpty())
|
|
|
|
return false;
|
|
|
|
return (!token.startsWith('\'') && token.contains('"'));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isCharLiteral(const QString& token) const{
|
|
|
|
if (token.isEmpty())
|
|
|
|
return false;
|
|
|
|
return (token.startsWith('\''));
|
|
|
|
}
|
2022-11-04 20:27:35 +08:00
|
|
|
|
|
|
|
bool isKeyword(const QString& token) const {
|
|
|
|
return mCppKeywords.contains(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tokenIsIdentifier(const QString& token) const {
|
|
|
|
//token won't be empty
|
|
|
|
return isIdentChar(token[0]);
|
|
|
|
}
|
|
|
|
|
2022-11-05 18:58:15 +08:00
|
|
|
bool tokenIsTypeOrNonKeyword(const QString& token) const {
|
|
|
|
return tokenIsIdentifier(token) &&
|
|
|
|
(mCppTypeKeywords.contains(token)
|
|
|
|
|| !mCppKeywords.contains(token)
|
|
|
|
|| token=="const");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-12-07 08:23:27 +08:00
|
|
|
PStatement doParseEvalTypeInfo(
|
|
|
|
const QString& fileName,
|
|
|
|
const PStatement& scope,
|
|
|
|
const QString& type,
|
|
|
|
QString& baseType,
|
2022-11-29 12:06:29 +08:00
|
|
|
PStatement& typeStatement,
|
|
|
|
int& pointerLevel,
|
|
|
|
QString& templateParams);
|
2021-12-07 08:23:27 +08:00
|
|
|
|
2021-08-22 21:23:58 +08:00
|
|
|
int getBracketEnd(const QString& s, int startAt);
|
2022-10-31 19:37:24 +08:00
|
|
|
StatementClassScope getClassScope(const QString& text);
|
2022-11-01 09:02:17 +08:00
|
|
|
StatementClassScope getClassScope(KeywordType keywordType);
|
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
|
2022-11-30 09:54:23 +08:00
|
|
|
QString getTemplateParam(const PStatement& statement, const QString& filename,
|
|
|
|
const QString& phrase, int index, const PStatement& currentScope);
|
2022-11-29 16:48:40 +08:00
|
|
|
int getTemplateParamStart(const QString& s, int startAt, int index);
|
|
|
|
int getTemplateParamEnd(const QString& s, int startAt);
|
2021-08-22 21:23:58 +08:00
|
|
|
|
2021-08-22 16:08:46 +08:00
|
|
|
void getFullNamespace(
|
2021-08-16 00:47:35 +08:00
|
|
|
const QString& phrase,
|
|
|
|
QString& sNamespace,
|
|
|
|
QString& member);
|
2021-08-17 23:30:14 +08:00
|
|
|
QString getFullStatementName(
|
|
|
|
const QString& command,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& parent);
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement getIncompleteClass(
|
|
|
|
const QString& command,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& parentScope);
|
2021-08-29 22:08:43 +08:00
|
|
|
QString getScopePrefix(const PStatement& statement);
|
2021-08-16 00:47:35 +08:00
|
|
|
StatementScope getScope();
|
2021-08-17 23:30:14 +08:00
|
|
|
QString getStatementKey(const QString& sName,
|
|
|
|
const QString& sType,
|
|
|
|
const QString& sNoNameArgs);
|
2021-08-29 00:48:23 +08:00
|
|
|
PStatement getTypeDef(const PStatement& statement,
|
|
|
|
const QString& fileName, const QString& aType);
|
2021-08-17 23:30:14 +08:00
|
|
|
void handleCatchBlock();
|
2022-11-01 22:10:54 +08:00
|
|
|
void handleEnum(bool isTypedef);
|
2021-08-17 23:30:14 +08:00
|
|
|
void handleForBlock();
|
2022-11-01 09:02:17 +08:00
|
|
|
void handleKeyword(KeywordType skipType);
|
2022-11-05 18:58:15 +08:00
|
|
|
void handleLambda(int index, int endIndex);
|
2021-08-19 12:01:01 +08:00
|
|
|
void handleMethod(
|
2022-11-04 20:27:35 +08:00
|
|
|
StatementKind functionKind,
|
2021-08-15 04:31:57 +08:00
|
|
|
const QString& sType,
|
|
|
|
const QString& sName,
|
2022-10-31 19:37:24 +08:00
|
|
|
int argStart,
|
2021-08-15 04:31:57 +08:00
|
|
|
bool isStatic,
|
|
|
|
bool isFriend);
|
2022-11-01 09:02:17 +08:00
|
|
|
void handleNamespace(KeywordType skipType);
|
2021-08-17 23:30:14 +08:00
|
|
|
void handleOtherTypedefs();
|
|
|
|
void handlePreprocessor();
|
2022-11-01 09:02:17 +08:00
|
|
|
void handleScope(KeywordType keywordType);
|
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();
|
2022-11-04 20:27:35 +08:00
|
|
|
void handleVar(const QString& typePrefix,bool isExtern,bool isStatic);
|
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(
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& derived,
|
2021-08-15 04:31:57 +08:00
|
|
|
bool isStruct,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& base,
|
2021-08-15 04:31:57 +08:00
|
|
|
StatementClassScope access);
|
2021-08-16 00:47:35 +08:00
|
|
|
PStatement doFindStatementInScope(const QString& name,
|
|
|
|
const QString& noNameArgs,
|
|
|
|
StatementKind kind,
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& scope);
|
2021-08-15 04:31:57 +08:00
|
|
|
void internalInvalidateFile(const QString& fileName);
|
2021-08-22 21:23:58 +08:00
|
|
|
void internalInvalidateFiles(const QSet<QString>& files);
|
|
|
|
QSet<QString> calculateFilesToBeReparsed(const QString& fileName);
|
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(
|
2021-08-29 00:48:23 +08:00
|
|
|
const PStatement& functionStatement,
|
2022-11-05 08:42:54 +08:00
|
|
|
int argStart);
|
2022-04-17 19:49:04 +08:00
|
|
|
QString splitPhrase(const QString& phrase, QString& sClazz,
|
|
|
|
QString& sOperator, QString &sMember);
|
2022-11-04 20:27:35 +08:00
|
|
|
QString removeTemplateParams(const QString& phrase);
|
2021-08-15 16:49:37 +08:00
|
|
|
|
2022-11-04 20:27:35 +08:00
|
|
|
bool splitLastMember(const QString& token, QString& lastMember, QString& remaining);
|
2021-08-15 17:52:39 +08:00
|
|
|
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isSpaceChar(const QChar& ch) const {
|
|
|
|
return ch==' ' || ch =='\t';
|
|
|
|
}
|
2021-08-15 17:52:39 +08:00
|
|
|
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isWordChar(const QChar& ch) const {
|
|
|
|
return ch.isLetter()
|
|
|
|
|| ch == '_'
|
|
|
|
|| ch == '*'
|
|
|
|
|| ch == '&';
|
|
|
|
}
|
2021-08-15 20:25:54 +08:00
|
|
|
|
2022-11-04 20:27:35 +08:00
|
|
|
bool isIdentifier(const QChar& ch) const {
|
|
|
|
return ch.isLetter()
|
|
|
|
|| ch == '_'
|
|
|
|
|| ch == '~'
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isIdentChar(const QChar& ch) const {
|
2022-03-23 12:30:58 +08:00
|
|
|
return ch.isLetter()
|
|
|
|
|| ch == '_';
|
|
|
|
}
|
2021-08-15 17:52:39 +08:00
|
|
|
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isDigitChar(const QChar& ch) const {
|
|
|
|
return (ch>='0' && ch<='9');
|
|
|
|
}
|
2021-08-15 17:52:39 +08:00
|
|
|
|
2022-11-02 22:48:25 +08:00
|
|
|
bool isInvalidFunctionArgsSuffixChar(const QChar& ch) const {
|
2022-11-03 00:49:22 +08:00
|
|
|
|
|
|
|
// &&
|
2022-11-02 22:48:25 +08:00
|
|
|
switch(ch.unicode()){
|
|
|
|
case '.':
|
|
|
|
case '-':
|
|
|
|
case '+':
|
|
|
|
case '/':
|
|
|
|
case '%':
|
|
|
|
case '*':
|
|
|
|
case '|':
|
|
|
|
case '?':
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-15 17:52:39 +08:00
|
|
|
/*'(', ';', ':', '{', '}', '#' */
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isSeperator(const QChar& ch) const {
|
|
|
|
switch(ch.unicode()){
|
|
|
|
case '(':
|
|
|
|
case ';':
|
|
|
|
case ':':
|
|
|
|
case '{':
|
|
|
|
case '}':
|
|
|
|
case '#':
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-08-15 17:52:39 +08:00
|
|
|
|
2021-08-18 05:34:04 +08:00
|
|
|
/*';', '{', '}'*/
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isblockChar(const QChar& ch) const {
|
|
|
|
switch(ch.unicode()){
|
|
|
|
case ';':
|
|
|
|
case '{':
|
|
|
|
case '}':
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-08-18 05:34:04 +08:00
|
|
|
|
2021-08-16 00:47:35 +08:00
|
|
|
/* '#', ',', ';', ':', '{', '}', '!', '/', '+', '-', '<', '>' */
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isInvalidVarPrefixChar(const QChar& ch) const {
|
|
|
|
switch (ch.unicode()) {
|
|
|
|
case '#':
|
|
|
|
case ',':
|
|
|
|
case ';':
|
|
|
|
case ':':
|
|
|
|
case '{':
|
|
|
|
case '}':
|
|
|
|
case '!':
|
|
|
|
case '/':
|
|
|
|
case '+':
|
|
|
|
case '-':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-08-16 00:47:35 +08:00
|
|
|
|
2021-08-18 17:02:57 +08:00
|
|
|
/*'{', '}' */
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isBraceChar(const QChar& ch) const {
|
|
|
|
return ch == '{' || ch =='}';
|
|
|
|
}
|
2021-08-18 17:02:57 +08:00
|
|
|
|
2022-03-23 12:30:58 +08:00
|
|
|
bool isLineChar(const QChar& ch) const {
|
|
|
|
return ch=='\n' || ch=='\r';
|
|
|
|
}
|
2021-08-15 20:25:54 +08:00
|
|
|
|
2022-11-04 20:27:35 +08:00
|
|
|
bool isNotFuncArgs(int startIndex);
|
2021-08-15 20:25:54 +08:00
|
|
|
|
2021-08-17 23:30:14 +08:00
|
|
|
/**
|
|
|
|
* @brief Test if a statement is a class/struct/union/namespace/function
|
|
|
|
* @param kind
|
|
|
|
* @return
|
|
|
|
*/
|
2021-12-08 19:13:47 +08:00
|
|
|
bool isNamedScope(StatementKind kind) const;
|
2021-08-17 23:30:14 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Test if a statement is a class/struct/union/enum/enum class/typedef
|
|
|
|
* @param kind
|
|
|
|
* @return
|
|
|
|
*/
|
2021-12-08 19:13:47 +08:00
|
|
|
bool isTypeStatement(StatementKind kind) const;
|
2021-08-17 23:30:14 +08:00
|
|
|
|
2021-08-15 04:31:57 +08:00
|
|
|
void updateSerialId();
|
2021-12-04 18:38:54 +08:00
|
|
|
|
2022-11-05 18:58:15 +08:00
|
|
|
int indexOfNextSemicolon(int index, int endIndex=-1);
|
2022-11-09 22:22:33 +08:00
|
|
|
int indexOfNextPeriodOrSemicolon(int index, int endIndex=-1);
|
2022-11-03 00:49:22 +08:00
|
|
|
int indexOfNextSemicolonOrLeftBrace(int index);
|
2022-11-01 09:02:17 +08:00
|
|
|
int indexOfNextColon(int index);
|
|
|
|
int indexOfNextLeftBrace(int index);
|
|
|
|
int indexPassParenthesis(int index);
|
|
|
|
int indexPassBraces(int index);
|
2022-11-05 18:58:15 +08:00
|
|
|
int skipAssignment(int index, int endIndex);
|
2022-11-04 20:27:35 +08:00
|
|
|
void skipNextSemicolon(int index);
|
2022-11-09 22:22:33 +08:00
|
|
|
int moveToEndOfStatement(int index, bool checkLambda, int endIndex=-1);
|
|
|
|
// int moveToNextAssignmentOrEndOfStatement(int index, bool checkLambda, int endIndex=-1);
|
2022-11-04 20:27:35 +08:00
|
|
|
void skipParenthesis(int index);
|
2022-11-01 22:10:54 +08:00
|
|
|
QString mergeArgs(int startIndex, int endIndex);
|
|
|
|
void parseCommandTypeAndArgs(QString& command,
|
|
|
|
QString& typeSuffix,
|
|
|
|
QString& args);
|
2021-08-14 22:52:37 +08:00
|
|
|
private:
|
|
|
|
int mParserId;
|
2022-07-28 13:51:38 +08:00
|
|
|
ParserLanguage mLanguage;
|
2021-08-14 22:52:37 +08:00
|
|
|
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;
|
|
|
|
|
|
|
|
StatementClassScope mClassScope;
|
|
|
|
StatementModel mStatementList;
|
|
|
|
//It's used in preprocessor, so we can't use fIncludeList instead
|
2021-08-22 21:23:58 +08:00
|
|
|
|
2021-08-14 22:52:37 +08:00
|
|
|
CppTokenizer mTokenizer;
|
2022-10-22 10:44:10 +08:00
|
|
|
CppPreprocessor mPreprocessor;
|
2021-08-15 04:31:57 +08:00
|
|
|
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;
|
|
|
|
int mLockCount; // lock(don't reparse) when we need to find statements in a batch
|
|
|
|
bool mParsing;
|
2022-10-18 19:09:46 +08:00
|
|
|
QHash<QString,PStatementList> mNamespaces; // namespace and the statements in its scope
|
2021-08-28 09:01:40 +08:00
|
|
|
QSet<QString> mInlineNamespaces;
|
2021-08-15 04:31:57 +08:00
|
|
|
|
2022-11-10 09:05:34 +08:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
|
|
|
QRecursiveMutex mMutex;
|
|
|
|
#else
|
2022-01-04 16:50:54 +08:00
|
|
|
QMutex mMutex;
|
2022-11-10 09:05:34 +08:00
|
|
|
#endif
|
2021-08-15 04:31:57 +08:00
|
|
|
GetFileStreamCallBack mOnGetFileStream;
|
2022-11-01 09:02:17 +08:00
|
|
|
QMap<QString,KeywordType> mCppKeywords;
|
2021-10-30 21:15:07 +08:00
|
|
|
QSet<QString> mCppTypeKeywords;
|
2021-08-14 22:52:37 +08:00
|
|
|
};
|
2021-08-23 03:47:28 +08:00
|
|
|
using PCppParser = std::shared_ptr<CppParser>;
|
2021-08-23 10:16:06 +08:00
|
|
|
|
|
|
|
class CppFileParserThread : public QThread {
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit CppFileParserThread(
|
|
|
|
PCppParser parser,
|
|
|
|
QString fileName,
|
|
|
|
bool inProject,
|
|
|
|
bool onlyIfNotParsed = false,
|
|
|
|
bool updateView = true,
|
|
|
|
QObject *parent = nullptr);
|
|
|
|
|
|
|
|
private:
|
|
|
|
PCppParser mParser;
|
|
|
|
QString mFileName;
|
|
|
|
bool mInProject;
|
|
|
|
bool mOnlyIfNotParsed;
|
|
|
|
bool mUpdateView;
|
|
|
|
|
|
|
|
// QThread interface
|
|
|
|
protected:
|
|
|
|
void run() override;
|
|
|
|
};
|
|
|
|
using PCppParserThread = std::shared_ptr<CppFileParserThread>;
|
|
|
|
|
|
|
|
class CppFileListParserThread: public QThread {
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit CppFileListParserThread(
|
|
|
|
PCppParser parser,
|
|
|
|
bool updateView = true,
|
|
|
|
QObject *parent = nullptr);
|
|
|
|
private:
|
|
|
|
PCppParser mParser;
|
|
|
|
bool mUpdateView;
|
|
|
|
// QThread interface
|
|
|
|
protected:
|
|
|
|
void run() override;
|
|
|
|
};
|
|
|
|
|
|
|
|
void parseFile(
|
|
|
|
PCppParser parser,
|
2021-08-29 00:48:23 +08:00
|
|
|
const QString& fileName,
|
2021-08-23 10:16:06 +08:00
|
|
|
bool inProject,
|
|
|
|
bool onlyIfNotParsed = false,
|
|
|
|
bool updateView = true);
|
|
|
|
|
|
|
|
void parseFileList(
|
|
|
|
PCppParser parser,
|
|
|
|
bool updateView = true);
|
|
|
|
|
|
|
|
|
2021-08-14 22:52:37 +08:00
|
|
|
#endif // CPPPARSER_H
|