summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp35
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp168
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h13
3 files changed, 195 insertions, 21 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 81df5e2351..55e1d69492 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -946,6 +946,18 @@ private:
ClassOrNamespace *_binding;
};
+static bool isTypeTypedefed(const FullySpecifiedType &originalTy,
+ const FullySpecifiedType &typedefedTy)
+{
+ return ! originalTy.isEqualTo(typedefedTy);
+}
+
+static bool areOriginalAndTypedefedTypePointer(const FullySpecifiedType &originalTy,
+ const FullySpecifiedType &typedefedTy)
+{
+ return originalTy->isPointerType() && typedefedTy->isPointerType();
+}
+
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
int accessOp,
bool *replacedDotOperator) const
@@ -1035,23 +1047,12 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
}
} else if (accessOp == T_DOT) {
if (replacedDotOperator) {
- *replacedDotOperator = originalType->isPointerType() || ty->isPointerType();
- // replace . with ->
- if (PointerType *ptrTy = originalType->asPointerType()) {
- // case when original type is a pointer and
- // typedef is for type
- // e.g.:
- // typedef S SType;
- // SType *p;
- ty = ptrTy->elementType();
- }
- else if (PointerType *ptrTy = ty->asPointerType()) {
- // case when original type is a type and
- // typedef is for pointer of type
- // e.g.:
- // typedef S* SPTR;
- // SPTR p;
- ty = ptrTy->elementType();
+ if (! isTypeTypedefed(originalType, ty)
+ || ! areOriginalAndTypedefedTypePointer(originalType, ty)) {
+ *replacedDotOperator = originalType->isPointerType() || ty->isPointerType();
+ if (PointerType *ptrTy = ty->asPointerType()) {
+ ty = ptrTy->elementType();
+ }
}
}
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index c1012f3527..a3b56ca108 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -1473,7 +1473,61 @@ void CppToolsPlugin::test_completion_member_access_operator_1()
QVERIFY(replaceAccessOperator);
}
-void CppToolsPlugin::test_completion_typedef_of_type_and_replace_access_operator()
+void CppToolsPlugin::test_completion_typedef_of_type_and_decl_of_type_no_replace_access_operator()
+{
+ TestData data;
+ data.srcText = "\n"
+ "struct S { int m; };\n"
+ "typedef S SType;\n"
+ "SType p;\n"
+ "@\n"
+ "}\n"
+ ;
+ setup(&data);
+
+ Utils::ChangeSet change;
+ QString txt = QLatin1String("p.");
+ change.insert(data.pos, txt);
+ QTextCursor cursor(data.doc);
+ change.apply(&cursor);
+ data.pos += txt.length();
+
+ bool replaceAccessOperator = false;
+ QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+ QCOMPARE(completions.size(), 2);
+ QVERIFY(completions.contains(QLatin1String("S")));
+ QVERIFY(completions.contains(QLatin1String("m")));
+ QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator()
+{
+ TestData data;
+ data.srcText = "\n"
+ "struct S { int m; };\n"
+ "typedef S *SType;\n"
+ "SType *p;\n"
+ "@\n"
+ "}\n"
+ ;
+ setup(&data);
+
+ Utils::ChangeSet change;
+ QString txt = QLatin1String("p.");
+ change.insert(data.pos, txt);
+ QTextCursor cursor(data.doc);
+ change.apply(&cursor);
+ data.pos += txt.length();
+
+ bool replaceAccessOperator = false;
+ QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+ QCOMPARE(completions.size(), 0);
+ QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_typedef_of_type_and_decl_of_pointer_replace_access_operator()
{
TestData data;
data.srcText = "\n"
@@ -1501,7 +1555,7 @@ void CppToolsPlugin::test_completion_typedef_of_type_and_replace_access_operator
QVERIFY(replaceAccessOperator);
}
-void CppToolsPlugin::test_completion_typedef_of_pointer_of_type_and_replace_access_operator()
+void CppToolsPlugin::test_completion_typedef_of_pointer_and_decl_of_type_replace_access_operator()
{
TestData data;
data.srcText = "\n"
@@ -1529,6 +1583,116 @@ void CppToolsPlugin::test_completion_typedef_of_pointer_of_type_and_replace_acce
QVERIFY(replaceAccessOperator);
}
+void CppToolsPlugin::test_completion_predecl_typedef_of_type_and_decl_of_pointer_replace_access_operator()
+{
+ TestData data;
+ data.srcText = "\n"
+ "typedef struct S SType;\n"
+ "struct S { int m; };\n"
+ "SType *p;\n"
+ "@\n"
+ "}\n"
+ ;
+ setup(&data);
+
+ Utils::ChangeSet change;
+ QString txt = QLatin1String("p.");
+ change.insert(data.pos, txt);
+ QTextCursor cursor(data.doc);
+ change.apply(&cursor);
+ data.pos += txt.length();
+
+ bool replaceAccessOperator = false;
+ QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+ QCOMPARE(completions.size(), 2);
+ QVERIFY(completions.contains(QLatin1String("S")));
+ QVERIFY(completions.contains(QLatin1String("m")));
+ QVERIFY(replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_predecl_typedef_of_type_and_decl_type_no_replace_access_operator()
+{
+ TestData data;
+ data.srcText = "\n"
+ "typedef struct S SType;\n"
+ "struct S { int m; };\n"
+ "SType p;\n"
+ "@\n"
+ "}\n"
+ ;
+ setup(&data);
+
+ Utils::ChangeSet change;
+ QString txt = QLatin1String("p.");
+ change.insert(data.pos, txt);
+ QTextCursor cursor(data.doc);
+ change.apply(&cursor);
+ data.pos += txt.length();
+
+ bool replaceAccessOperator = false;
+ QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+ QCOMPARE(completions.size(), 2);
+ QVERIFY(completions.contains(QLatin1String("S")));
+ QVERIFY(completions.contains(QLatin1String("m")));
+ QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_predecl_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator()
+{
+ TestData data;
+ data.srcText = "\n"
+ "typedef struct S *SType;\n"
+ "struct S { int m; };\n"
+ "SType *p;\n"
+ "@\n"
+ "}\n"
+ ;
+ setup(&data);
+
+ Utils::ChangeSet change;
+ QString txt = QLatin1String("p.");
+ change.insert(data.pos, txt);
+ QTextCursor cursor(data.doc);
+ change.apply(&cursor);
+ data.pos += txt.length();
+
+ bool replaceAccessOperator = false;
+ QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+ QCOMPARE(completions.size(), 0);
+ QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_predecl_typedef_of_pointer_and_decl_of_type_replace_access_operator()
+{
+ TestData data;
+ data.srcText = "\n"
+ "typedef struct S *SType;\n"
+ "struct S { int m; };\n"
+ "SType p;\n"
+ "@\n"
+ "}\n"
+ ;
+ setup(&data);
+
+ Utils::ChangeSet change;
+ QString txt = QLatin1String("p.");
+ change.insert(data.pos, txt);
+ QTextCursor cursor(data.doc);
+ change.apply(&cursor);
+ data.pos += txt.length();
+
+ bool replaceAccessOperator = false;
+ QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+ QCOMPARE(completions.size(), 2);
+ QVERIFY(completions.contains(QLatin1String("S")));
+ QVERIFY(completions.contains(QLatin1String("m")));
+ QVERIFY(replaceAccessOperator);
+}
+
void CppToolsPlugin::test_completion_typedef_of_pointer()
{
TestData data;
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index a8ab4bbc29..5e4d143850 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -113,8 +113,17 @@ private slots:
void test_completion_instantiate_template_with_default_argument_type();
void test_completion_instantiate_template_with_default_argument_type_as_template();
void test_completion_member_access_operator_1();
- void test_completion_typedef_of_type_and_replace_access_operator();
- void test_completion_typedef_of_pointer_of_type_and_replace_access_operator();
+
+ void test_completion_typedef_of_type_and_decl_of_type_no_replace_access_operator();
+ void test_completion_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator();
+ void test_completion_typedef_of_type_and_decl_of_pointer_replace_access_operator();
+ void test_completion_typedef_of_pointer_and_decl_of_type_replace_access_operator();
+
+ void test_completion_predecl_typedef_of_type_and_decl_of_pointer_replace_access_operator();
+ void test_completion_predecl_typedef_of_type_and_decl_type_no_replace_access_operator();
+ void test_completion_predecl_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator();
+ void test_completion_predecl_typedef_of_pointer_and_decl_of_type_replace_access_operator();
+
void test_completion_typedef_of_pointer();
void test_completion_typedef_of_pointer_inside_function();
void test_completion_typedef_is_inside_function_before_declaration_block();