[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