diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 81df5e23515a36ec4ddcc8f367edf029c235ed7c..55e1d694928e5adcc408bccdca45f8bc7eb05d31 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 c1012f3527761429e89fdd54795c6498d56418d1..a3b56ca10844e1f940773afefd3ed4e7d17f5910 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 a8ab4bbc291e1b76424d3832c28b58e6cd0ec0d8..5e4d14385068056abb2394a054737a66b72a2e79 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();