[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kdev-clang] /: Add protected members into completions
From:       Sergey Kalinichev <kalinichev.so.0 () gmail ! com>
Date:       2015-07-31 19:12:18
Message-ID: E1ZLFj8-00072O-RD () scm ! kde ! org
[Download RAW message or body]

Git commit af76c02d5837bfce197da4639a0e3d27d904887c by Sergey Kalinichev.
Committed on 31/07/2015 at 17:59.
Pushed by skalinichev into branch 'master'.

Add protected members into completions

This should work around the issue with protected members from base
classes marked as not accessible in derived classes.

See also: https://llvm.org/bugs/show_bug.cgi?id=24329

REVIEW: 124506

M  +40   -1    codecompletion/context.cpp
M  +12   -0    tests/test_codecompletion.cpp

http://commits.kde.org/kdev-clang/af76c02d5837bfce197da4639a0e3d27d904887c

diff --git a/codecompletion/context.cpp b/codecompletion/context.cpp
index 61c666e..dafad2e 100644
--- a/codecompletion/context.cpp
+++ b/codecompletion/context.cpp
@@ -25,6 +25,7 @@
 #include <language/duchain/ducontext.h>
 #include <language/duchain/topducontext.h>
 #include <language/duchain/declaration.h>
+#include <language/duchain/classmemberdeclaration.h>
 #include <language/duchain/duchainutils.h>
 #include <language/duchain/types/functiontype.h>
 #include <language/duchain/types/typealiastype.h>
@@ -508,6 +509,20 @@ Declaration* findDeclaration(const QualifiedIdentifier& qid, \
const DUContextPoin  return nullptr;
 }
 
+/// If any parent of this context is a class, the closest class declaration is \
returned, nullptr otherwise +Declaration* classDeclarationForContext(const \
DUContextPointer& context) +{
+    auto parent = context;
+    while (parent) {
+        if (parent->type() == DUContext::Class) {
+            break;
+        }
+        parent = parent->parentContext();
+    }
+
+    return parent ? parent->owner() : nullptr;
+}
+
 }
 
 ClangCodeCompletionContext::ClangCodeCompletionContext(const DUContextPointer& \
context, @@ -600,7 +615,7 @@ QList<CompletionTreeItemPointer> \
ClangCodeCompletionContext::completionItems(boo  auto result = m_results->Results[i];
 
         const auto availability = \
                clang_getCompletionAvailability(result.CompletionString);
-        if (availability == CXAvailability_NotAvailable || availability == \
CXAvailability_NotAccessible) { +        if (availability == \
CXAvailability_NotAvailable) {  continue;
         }
 
@@ -619,6 +634,10 @@ QList<CompletionTreeItemPointer> \
ClangCodeCompletionContext::completionItems(boo  continue;
         }
 
+        if (availability == CXAvailability_NotAccessible && (!isDeclaration || \
!classDeclarationForContext(ctx))) { +            continue;
+        }
+
         const uint chunks = clang_getNumCompletionChunks(result.CompletionString);
 
         // the string that would be needed to type, usually the identifier of \
something. Also we use it as name for code completion declaration items. @@ -717,6 \
+736,26 @@ QList<CompletionTreeItemPointer> \
ClangCodeCompletionContext::completionItems(boo  
             CompletionTreeItemPointer item;
             if (found) {
+                // TODO: Bug in Clang: protected members from base classes not \
accessible in derived classes. +                if (availability == \
CXAvailability_NotAccessible) { +                    if (auto cl = \
dynamic_cast<ClassMemberDeclaration*>(found)) { +                        if \
(cl->accessPolicy() != Declaration::Protected) { +                            \
continue; +                        }
+
+                        auto declarationClassContext = \
classDeclarationForContext(DUContextPointer(found->context())); +                     \
auto currentClassContext = classDeclarationForContext(ctx); +
+                        uint steps = 10;
+                        auto inheriters = \
DUChainUtils::getInheriters(declarationClassContext, steps); +                        \
if(!inheriters.contains(currentClassContext)){ +                            continue;
+                        }
+                    } else {
+                        continue;
+                    }
+                }
+
                 auto declarationItem = new DeclarationItem(found, display, \
resultType, replacement);  
                 const unsigned int completionPriority = \
adjustPriorityForDeclaration(found, \
                clang_getCompletionPriority(result.CompletionString));
diff --git a/tests/test_codecompletion.cpp b/tests/test_codecompletion.cpp
index 62b2e48..1b569f0 100644
--- a/tests/test_codecompletion.cpp
+++ b/tests/test_codecompletion.cpp
@@ -177,6 +177,7 @@ void executeCompletionPriorityTest(const QString& code, const \
CompletionPriority  
     for(const auto& declaration : expectedCompletionItems.completions){
         const auto declarationItem = tester.findItem(declaration.name);
+        QEXPECT_FAIL("protected-access2", \
declaration.failMessage.toUtf8().constData(), Abort);  QVERIFY(declarationItem);
         QVERIFY(declarationItem->declaration());
 
@@ -713,4 +714,15 @@ void TestCodeCompletion::testCompletionPriority_data()
         << "template <typename T> class Class{}; template <typename T> class \
Class2{};"  "int main(){ Class<int> a; Class2<int> b =\n }"
         << CompletionPriorityItems{{1,0}, {{"b", 9, 0}, {"a", 0, 21}}};
+
+    QTest::newRow("protected-access")
+        << "class Base { protected: int m_protected; };"
+           "class Derived: public Base {public: void g(){\n }};"
+        << CompletionPriorityItems{{1,0}, {{"m_protected", 0, 37}}};
+
+    QTest::newRow("protected-access2")
+        << "class Base { protected: int m_protected; };"
+           "class Derived: public Base {public: void f();};"
+           "void Derived::f(){\n }"
+        << CompletionPriorityItems{{1,0}, {{"m_protected", 0, 37, \
QStringLiteral("Out of line methods have wrong parent context attached (Global \
instead of Class)")}}};  }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic