ClangCodeModel: Fix access type categorization for functions

... with clangd.
The code is starting to look rather hacky and might need to be rewritten
completely at some point. Let's see how far we get with it.

Change-Id: I506dd410831970b9f9291b005129b4d70f397de0
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-12-09 17:59:10 +01:00
parent 3989245562
commit fc3b7f7ac5
3 changed files with 27 additions and 4 deletions

View File

@@ -477,7 +477,9 @@ static QList<AstNode> getAstPath(const AstNode &root, const Position &pos)
static Usage::Type getUsageType(const QList<AstNode> &path)
{
bool potentialWrite = false;
bool isFunction = false;
const bool symbolIsDataType = path.last().role() == "type" && path.last().kind() == "Record";
const auto isPotentialWrite = [&] { return potentialWrite && !isFunction; };
for (auto pathIt = path.rbegin(); pathIt != path.rend(); ++pathIt) {
if (pathIt->arcanaContains("non_odr_use_unevaluated"))
return Usage::Type::Other;
@@ -487,10 +489,23 @@ static Usage::Type getUsageType(const QList<AstNode> &path)
return Usage::Type::Other;
if (pathIt->kind() == "Switch" || pathIt->kind() == "If")
return Usage::Type::Read;
if (pathIt->kind() == "Call" || pathIt->kind() == "CXXMemberCall")
return potentialWrite ? Usage::Type::WritableRef : Usage::Type::Read;
if (pathIt->kind() == "Call")
return isFunction ? Usage::Type::Other
: potentialWrite ? Usage::Type::WritableRef : Usage::Type::Read;
if (pathIt->kind() == "CXXMemberCall") {
const auto children = pathIt->children();
if (children && children->size() == 1
&& children->first() == path.last()
&& children->first().arcanaContains("bound member function")) {
return Usage::Type::Other;
}
return isPotentialWrite() ? Usage::Type::WritableRef : Usage::Type::Read;
}
if ((pathIt->kind() == "DeclRef" || pathIt->kind() == "Member")
&& pathIt->arcanaContains("lvalue")) {
if (pathIt->arcanaContains(" Function "))
isFunction = true;
else
potentialWrite = true;
}
if (pathIt->role() == "declaration") {
@@ -501,6 +516,8 @@ static Usage::Type getUsageType(const QList<AstNode> &path)
return Usage::Type::Initialization;
if (pathIt->childContainsRange(0, path.last().range()))
return Usage::Type::Initialization;
if (isFunction)
return Usage::Type::Read;
if (!pathIt->hasConstType())
return Usage::Type::WritableRef;
return Usage::Type::Read;
@@ -528,7 +545,7 @@ static Usage::Type getUsageType(const QList<AstNode> &path)
const int lhsIndex = isBinaryOp ? 0 : 1;
if (pathIt->childContainsRange(lhsIndex, path.last().range()))
return Usage::Type::Write;
return potentialWrite ? Usage::Type::WritableRef : Usage::Type::Read;
return isPotentialWrite() ? Usage::Type::WritableRef : Usage::Type::Read;
}
return Usage::Type::Read;
}

View File

@@ -284,6 +284,11 @@ void ClangdTestFindReferences::test_data()
QTest::newRow("array variable") << "main.cpp" << 1134 << ItemList{
makeItem(57, 8, Usage::Type::Declaration), makeItem(58, 4, Usage::Type::Write),
makeItem(59, 15, Usage::Type::Read)};
QTest::newRow("free function") << "defs.h" << 510 << ItemList{
makeItem(24, 5, Usage::Type::Declaration), makeItem(19, 4, Usage::Type::Other),
makeItem(25, 4, Usage::Type::Other), makeItem(60, 26, Usage::Type::Read)};
QTest::newRow("member function") << "defs.h" << 192 << ItemList{
makeItem(9, 12, Usage::Type::Declaration), makeItem(40, 8, Usage::Type::Other)};
}
// The main point here is to test our access type categorization.

View File

@@ -57,4 +57,5 @@ int main()
int array[3];
array[S::value] = S::value;
S::value = array[S::value];
const auto funcPtr = &func1;
}