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();
});
// get full phrase (such as s.name instead of name)
BufferCoord pBeginPos,pEndPos;
QString phrase = getWordAtPosition(editor,pos,pBeginPos,pEndPos,Editor::WordPurpose::wpInformation);
QStringList expression = editor->getExpressionAtPosition(pos);
// Find it's definition
PStatement statement = editor->parser()->findStatementOf(
editor->filename(),
phrase,
pos.Line);
expression,
editor->parser()->findAndScanBlockAt(editor->filename(),pos.Line));
// definition of the symbol not found
if (!statement)
return false;

View File

@ -1631,51 +1631,7 @@ QStringList Editor::getOwnerExpressionAndMemberAtPositionForCompletion(
QStringList &memberExpression)
{
QStringList expression = getExpressionAtPosition(pos);
//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 (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;
return getOwnerExpressionAndMember(expression,memberOperator,memberExpression);
}
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...
QString result;
PStatement statement;
if (expression.count()>1) {
PEvalStatement evalStatement = mParser->evalExpression(
PStatement statement = mParser->findStatementOf(
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)
return result;
if (statement->kind == StatementKind::skFunction

View File

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

View File

@ -39,11 +39,6 @@ CppParser::CppParser(QObject *parent) : QObject(parent)
//mBlockBeginSkips;
//mBlockEndSkips;
//mInlineNamespaceEndSkips;
mMemberOperators.insert(".");
mMemberOperators.insert("::");
mMemberOperators.insert("->");
mMemberOperators.insert("->*");
mMemberOperators.insert(".*");
}
CppParser::~CppParser()
@ -420,6 +415,38 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
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 scopeStatement = startScope;
@ -4608,10 +4635,7 @@ void CppParser::updateSerialId()
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
}
bool CppParser::isMemberOperator(QString token) const
{
return mMemberOperators.contains(token);
}
const StatementModel &CppParser::statementList() const
{

View File

@ -49,6 +49,10 @@ public:
const QString& phrase,
const PStatement& currentClass,
bool force = false);
PStatement findStatementOf(const QString& fileName,
const QStringList& expression,
const PStatement& currentScope);
/**
* @brief evaluate the expression
* @param fileName
@ -86,13 +90,6 @@ public:
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;
void setEnabled(bool newEnabled);
@ -452,7 +449,6 @@ private:
GetFileStreamCallBack mOnGetFileStream;
QMap<QString,SkipType> mCppKeywords;
QSet<QString> mCppTypeKeywords;
QSet<QString> mMemberOperators;
};
using PCppParser = std::shared_ptr<CppParser>;

View File

@ -15,6 +15,7 @@ QSet<QString> CKeywords;
QSet<QString> STLPointers;
QSet<QString> STLContainers;
QSet<QString> STLElementMethods;
QSet<QString> MemberOperators;
Q_GLOBAL_STATIC(QSet<QString>,CppHeaderExts)
Q_GLOBAL_STATIC(QSet<QString>,CppSourceExts)
@ -293,6 +294,12 @@ void initParser()
JavadocTags.append("@throws");
JavadocTags.append("@value");
JavadocTags.append("@version");
MemberOperators.insert(".");
MemberOperators.insert("::");
MemberOperators.insert("->");
MemberOperators.insert("->*");
MemberOperators.insert(".*");
}
QString getHeaderFilename(const QString &relativeTo, const QString &line,
@ -520,3 +527,58 @@ void EvalStatement::assignType(const PEvalStatement &typeStatement)
pointerLevel = typeStatement->pointerLevel;
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> STLContainers;
extern QSet<QString> STLElementMethods;
extern QSet<QString> MemberOperators;
void initParser();
@ -240,5 +241,10 @@ bool isCfile(const QString& filename);
bool isKeyword(const QString& word);
bool isScopeTypeKind(StatementKind kind);
MemberOperatorType getOperatorType(const QString& phrase, int index);
QStringList getOwnerExpressionAndMember(
const QStringList expression,
QString& memberOperator,
QStringList& memberExpression);
bool isMemberOperator(QString token);
#endif // PARSER_UTILS_H