add a function to find statement by expression in the parser

This commit is contained in:
Roy Qu 2021-12-18 23:36:58 +08:00
parent cd5b281c90
commit 41336cf31f
7 changed files with 114 additions and 83 deletions

View File

@ -24,13 +24,12 @@ bool CppRefacter::findOccurence(Editor *editor, const BufferCoord &pos)
editor->parser()->unFreeze(); editor->parser()->unFreeze();
}); });
// get full phrase (such as s.name instead of name) // get full phrase (such as s.name instead of name)
BufferCoord pBeginPos,pEndPos; QStringList expression = editor->getExpressionAtPosition(pos);
QString phrase = getWordAtPosition(editor,pos,pBeginPos,pEndPos,Editor::WordPurpose::wpInformation);
// Find it's definition // Find it's definition
PStatement statement = editor->parser()->findStatementOf( PStatement statement = editor->parser()->findStatementOf(
editor->filename(), editor->filename(),
phrase, expression,
pos.Line); editor->parser()->findAndScanBlockAt(editor->filename(),pos.Line));
// definition of the symbol not found // definition of the symbol not found
if (!statement) if (!statement)
return false; return false;

View File

@ -1631,51 +1631,7 @@ QStringList Editor::getOwnerExpressionAndMemberAtPositionForCompletion(
QStringList &memberExpression) QStringList &memberExpression)
{ {
QStringList expression = getExpressionAtPosition(pos); QStringList expression = getExpressionAtPosition(pos);
//find position of the last member operator return getOwnerExpressionAndMember(expression,memberOperator,memberExpression);
int lastMemberOperatorPos = -1;
int currentMatchingLevel = 0;
QString matchingSignLeft;
QString matchingSignRight;
for (int i=0;i<expression.length();i++) {
QString token = expression[i];
if (currentMatchingLevel == 0) {
if (mParser->isMemberOperator(token)) {
lastMemberOperatorPos = i;
} else if (token == "(") {
matchingSignLeft = "(";
matchingSignRight = ")";
currentMatchingLevel++;
} else if (token == "[") {
matchingSignLeft = "[";
matchingSignRight = "]";
currentMatchingLevel++;
} else if (token == "<") {
matchingSignLeft = "<";
matchingSignRight = ">";
currentMatchingLevel++;
}
} else {
if (token == matchingSignLeft) {
currentMatchingLevel++;
} else if (token == matchingSignRight) {
currentMatchingLevel--;
}
}
}
QStringList ownerExpression;
if (lastMemberOperatorPos<0) {
memberOperator = "";
memberExpression = expression;
} else {
memberOperator = expression[lastMemberOperatorPos];
memberExpression = expression.mid(lastMemberOperatorPos+1);
ownerExpression = expression.mid(0,lastMemberOperatorPos);
}
if (memberExpression.length()>1) {
memberExpression = memberExpression.mid(memberExpression.length()-1,1);
}
return ownerExpression;
} }
QStringList Editor::getExpressionAtPosition( QStringList Editor::getExpressionAtPosition(
@ -3099,21 +3055,9 @@ QString Editor::getParserHint(const QStringList& expression,const QString &s, in
{ {
// This piece of code changes the parser database, possibly making hints and code completion invalid... // This piece of code changes the parser database, possibly making hints and code completion invalid...
QString result; QString result;
PStatement statement; PStatement statement = mParser->findStatementOf(
if (expression.count()>1) { mFilename,expression,
PEvalStatement evalStatement = mParser->evalExpression( mParser->findAndScanBlockAt(mFilename,line));
mFilename,expression,
mParser->findAndScanBlockAt(mFilename,line));
if (evalStatement) {
if (evalStatement->kind == EvalStatementKind::Type) {
statement = evalStatement->effectiveTypeStatement;
} else {
statement = evalStatement->baseStatement;
}
}
} else {
statement = mParser->findStatementOf(mFilename, s, line);
}
if (!statement) if (!statement)
return result; return result;
if (statement->kind == StatementKind::skFunction if (statement->kind == StatementKind::skFunction

View File

@ -199,6 +199,8 @@ public:
QString& memberOperator, QString& memberOperator,
QStringList& memberExpression); QStringList& memberExpression);
QString getWordForCompletionSearch(const BufferCoord& pos,bool permitTilde); QString getWordForCompletionSearch(const BufferCoord& pos,bool permitTilde);
QStringList getExpressionAtPosition(
const BufferCoord& pos);
const PCppParser &parser(); const PCppParser &parser();
@ -260,8 +262,6 @@ private:
void popUserCodeInTabStops(); void popUserCodeInTabStops();
void onExportedFormatToken(PSynHighlighter syntaxHighlighter, int Line, int column, const QString& token, void onExportedFormatToken(PSynHighlighter syntaxHighlighter, int Line, int column, const QString& token,
PSynHighlighterAttribute &attr); PSynHighlighterAttribute &attr);
QStringList getExpressionAtPosition(
const BufferCoord& pos);
private: private:
QByteArray mEncodingOption; // the encoding type set by the user QByteArray mEncodingOption; // the encoding type set by the user
QByteArray mFileEncoding; // the real encoding of the file (auto detected) QByteArray mFileEncoding; // the real encoding of the file (auto detected)

View File

@ -39,11 +39,6 @@ CppParser::CppParser(QObject *parent) : QObject(parent)
//mBlockBeginSkips; //mBlockBeginSkips;
//mBlockEndSkips; //mBlockEndSkips;
//mInlineNamespaceEndSkips; //mInlineNamespaceEndSkips;
mMemberOperators.insert(".");
mMemberOperators.insert("::");
mMemberOperators.insert("->");
mMemberOperators.insert("->*");
mMemberOperators.insert(".*");
} }
CppParser::~CppParser() CppParser::~CppParser()
@ -420,6 +415,38 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
return findStatementOf(fileName,phrase,currentClass,statementParentType,force); return findStatementOf(fileName,phrase,currentClass,statementParentType,force);
} }
PStatement CppParser::findStatementOf(const QString &fileName, const QStringList &expression, const PStatement &currentScope)
{
QMutexLocker locker(&mMutex);
if (mParsing)
return PStatement();
QString memberOperator;
QStringList memberExpression;
QStringList ownerExpression = getOwnerExpressionAndMember(expression,memberOperator,memberExpression);
if (memberExpression.isEmpty()) {
return PStatement();
}
QString phrase = memberExpression[0];
if (memberOperator.isEmpty()) {
return findStatementStartingFrom(fileName,phrase,currentScope);
} else if (ownerExpression.isEmpty()) {
return findMemberOfStatement(phrase,PStatement());
} else {
int pos = 0;
PEvalStatement ownerEvalStatement = doEvalExpression(fileName,
ownerExpression,
pos,
currentScope,
PEvalStatement(),
true);
if (!ownerEvalStatement) {
return PStatement();
}
return findMemberOfStatement(phrase, ownerEvalStatement->effectiveTypeStatement);
}
}
PStatement CppParser::findStatementStartingFrom(const QString &fileName, const QString &phrase, const PStatement& startScope) PStatement CppParser::findStatementStartingFrom(const QString &fileName, const QString &phrase, const PStatement& startScope)
{ {
PStatement scopeStatement = startScope; PStatement scopeStatement = startScope;
@ -4608,10 +4635,7 @@ void CppParser::updateSerialId()
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount); mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
} }
bool CppParser::isMemberOperator(QString token) const
{
return mMemberOperators.contains(token);
}
const StatementModel &CppParser::statementList() const const StatementModel &CppParser::statementList() const
{ {

View File

@ -49,6 +49,10 @@ public:
const QString& phrase, const QString& phrase,
const PStatement& currentClass, const PStatement& currentClass,
bool force = false); bool force = false);
PStatement findStatementOf(const QString& fileName,
const QStringList& expression,
const PStatement& currentScope);
/** /**
* @brief evaluate the expression * @brief evaluate the expression
* @param fileName * @param fileName
@ -86,13 +90,6 @@ public:
QString prettyPrintStatement(const PStatement& statement, const QString& filename, int line = -1); QString prettyPrintStatement(const PStatement& statement, const QString& filename, int line = -1);
/**
* @brief test if the token is a member/scope operator
* @param token
* @return true if it is, false if not
*/
bool isMemberOperator(QString token) const;
bool enabled() const; bool enabled() const;
void setEnabled(bool newEnabled); void setEnabled(bool newEnabled);
@ -452,7 +449,6 @@ private:
GetFileStreamCallBack mOnGetFileStream; GetFileStreamCallBack mOnGetFileStream;
QMap<QString,SkipType> mCppKeywords; QMap<QString,SkipType> mCppKeywords;
QSet<QString> mCppTypeKeywords; QSet<QString> mCppTypeKeywords;
QSet<QString> mMemberOperators;
}; };
using PCppParser = std::shared_ptr<CppParser>; using PCppParser = std::shared_ptr<CppParser>;

View File

@ -15,6 +15,7 @@ QSet<QString> CKeywords;
QSet<QString> STLPointers; QSet<QString> STLPointers;
QSet<QString> STLContainers; QSet<QString> STLContainers;
QSet<QString> STLElementMethods; QSet<QString> STLElementMethods;
QSet<QString> MemberOperators;
Q_GLOBAL_STATIC(QSet<QString>,CppHeaderExts) Q_GLOBAL_STATIC(QSet<QString>,CppHeaderExts)
Q_GLOBAL_STATIC(QSet<QString>,CppSourceExts) Q_GLOBAL_STATIC(QSet<QString>,CppSourceExts)
@ -293,6 +294,12 @@ void initParser()
JavadocTags.append("@throws"); JavadocTags.append("@throws");
JavadocTags.append("@value"); JavadocTags.append("@value");
JavadocTags.append("@version"); JavadocTags.append("@version");
MemberOperators.insert(".");
MemberOperators.insert("::");
MemberOperators.insert("->");
MemberOperators.insert("->*");
MemberOperators.insert(".*");
} }
QString getHeaderFilename(const QString &relativeTo, const QString &line, QString getHeaderFilename(const QString &relativeTo, const QString &line,
@ -520,3 +527,58 @@ void EvalStatement::assignType(const PEvalStatement &typeStatement)
pointerLevel = typeStatement->pointerLevel; pointerLevel = typeStatement->pointerLevel;
effectiveTypeStatement = typeStatement->effectiveTypeStatement; effectiveTypeStatement = typeStatement->effectiveTypeStatement;
} }
QStringList getOwnerExpressionAndMember(const QStringList expression, QString &memberOperator, QStringList &memberExpression)
{
//find position of the last member operator
int lastMemberOperatorPos = -1;
int currentMatchingLevel = 0;
QString matchingSignLeft;
QString matchingSignRight;
for (int i=0;i<expression.length();i++) {
QString token = expression[i];
if (currentMatchingLevel == 0) {
if (isMemberOperator(token)) {
lastMemberOperatorPos = i;
} else if (token == "(") {
matchingSignLeft = "(";
matchingSignRight = ")";
currentMatchingLevel++;
} else if (token == "[") {
matchingSignLeft = "[";
matchingSignRight = "]";
currentMatchingLevel++;
} else if (token == "<") {
matchingSignLeft = "<";
matchingSignRight = ">";
currentMatchingLevel++;
}
} else {
if (token == matchingSignLeft) {
currentMatchingLevel++;
} else if (token == matchingSignRight) {
currentMatchingLevel--;
}
}
}
QStringList ownerExpression;
if (lastMemberOperatorPos<0) {
memberOperator = "";
memberExpression = expression;
} else {
memberOperator = expression[lastMemberOperatorPos];
memberExpression = expression.mid(lastMemberOperatorPos+1);
ownerExpression = expression.mid(0,lastMemberOperatorPos);
}
if (memberExpression.length()>1) {
memberExpression = memberExpression.mid(memberExpression.length()-1,1);
}
return ownerExpression;
}
bool isMemberOperator(QString token)
{
return MemberOperators.contains(token);
}

View File

@ -225,6 +225,7 @@ extern QSet<QString> CppTypeKeywords;
extern QSet<QString> STLPointers; extern QSet<QString> STLPointers;
extern QSet<QString> STLContainers; extern QSet<QString> STLContainers;
extern QSet<QString> STLElementMethods; extern QSet<QString> STLElementMethods;
extern QSet<QString> MemberOperators;
void initParser(); void initParser();
@ -240,5 +241,10 @@ bool isCfile(const QString& filename);
bool isKeyword(const QString& word); bool isKeyword(const QString& word);
bool isScopeTypeKind(StatementKind kind); bool isScopeTypeKind(StatementKind kind);
MemberOperatorType getOperatorType(const QString& phrase, int index); MemberOperatorType getOperatorType(const QString& phrase, int index);
QStringList getOwnerExpressionAndMember(
const QStringList expression,
QString& memberOperator,
QStringList& memberExpression);
bool isMemberOperator(QString token);
#endif // PARSER_UTILS_H #endif // PARSER_UTILS_H