From fc3b7f7ac5ccb29a5217de658d4cb7d0ddb578e3 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 9 Dec 2021 17:59:10 +0100 Subject: [PATCH] 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: Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 25 ++++++++++++++++--- .../clangcodemodel/test/clangdtests.cpp | 5 ++++ .../test/data/find-usages/main.cpp | 1 + 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 1d5752ca1de..b76bc58b6cc 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -477,7 +477,9 @@ static QList getAstPath(const AstNode &root, const Position &pos) static Usage::Type getUsageType(const QList &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,11 +489,24 @@ static Usage::Type getUsageType(const QList &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")) { - potentialWrite = true; + if (pathIt->arcanaContains(" Function ")) + isFunction = true; + else + potentialWrite = true; } if (pathIt->role() == "declaration") { if (symbolIsDataType) @@ -501,6 +516,8 @@ static Usage::Type getUsageType(const QList &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 &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; } diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index 93aae99ecd3..5d9f6e03589 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -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. diff --git a/src/plugins/clangcodemodel/test/data/find-usages/main.cpp b/src/plugins/clangcodemodel/test/data/find-usages/main.cpp index 36941dc4735..6321c421527 100644 --- a/src/plugins/clangcodemodel/test/data/find-usages/main.cpp +++ b/src/plugins/clangcodemodel/test/data/find-usages/main.cpp @@ -57,4 +57,5 @@ int main() int array[3]; array[S::value] = S::value; S::value = array[S::value]; + const auto funcPtr = &func1; }