diff options
-rw-r--r-- | src/libs/3rdparty/cplusplus/Symbols.cpp | 106 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 5 | ||||
-rw-r--r-- | src/plugins/cpptools/cppcompletion_test.cpp | 163 |
3 files changed, 266 insertions, 8 deletions
diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp index 253bb04788..f7423e7742 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.cpp +++ b/src/libs/3rdparty/cplusplus/Symbols.cpp @@ -18,13 +18,18 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "Symbols.h" -#include "Names.h" -#include "TypeVisitor.h" -#include "SymbolVisitor.h" +#include "Control.h" +#include "CoreTypes.h" +#include "Literals.h" #include "Matcher.h" +#include "Names.h" #include "Scope.h" +#include "Symbols.h" +#include "SymbolVisitor.h" #include "Templates.h" +#include "TypeVisitor.h" + +#include <cstring> using namespace CPlusPlus; @@ -99,7 +104,98 @@ Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original) : Symbol(clone, subst, original) , _type(clone->type(original->_type, subst)) , _initializer(clone->stringLiteral(original->_initializer)) -{ } +{ + const char* nameId = nullptr; + if (const Identifier* identifier = name()->identifier()) + nameId = identifier->chars(); + else + return; + + Class *enClass = original->enclosingClass(); + const char* enClassNameId = nullptr; + if (enClass && enClass->name() && enClass->name()->identifier()) { + enClassNameId = enClass->name()->identifier()->chars(); + } else { + return; + } + + if (!enClassNameId) + return; + + Template *templSpec = enClass->enclosingTemplate(); + const char* enNamespaceNameId = nullptr; + if (templSpec) { + if (Namespace* ns = templSpec->enclosingNamespace()) { + if (ns->isInline()) + ns = ns->enclosingNamespace(); + + if (ns->name() && ns->name()->identifier()) + enNamespaceNameId =ns->name()->identifier()->chars(); + } + } + + if (!enNamespaceNameId || templSpec->templateParameterCount() < 1) + return; + + const Name *firstTemplParamName = nullptr; + if (const TypenameArgument *templParam = + templSpec->templateParameterAt(0)->asTypenameArgument()) { + firstTemplParamName = templParam->name(); + } + + if (!firstTemplParamName) + return; + + FullySpecifiedType newType; + if (std::strcmp(enNamespaceNameId, "std") == 0 || + std::strcmp(enNamespaceNameId, "__cxx11") == 0) { + if (std::strcmp(enClassNameId, "unique_ptr") == 0) { + if (std::strcmp(nameId, "pointer") == 0) { + newType = clone->type(subst->apply(firstTemplParamName), 0); + newType = FullySpecifiedType(clone->control()->pointerType(newType)); + } + } else if (std::strcmp(enClassNameId, "list") == 0 || + std::strcmp(enClassNameId, "forward_list") == 0 || + std::strcmp(enClassNameId, "vector") == 0 || + std::strcmp(enClassNameId, "queue") == 0 || + std::strcmp(enClassNameId, "deque") == 0 || + std::strcmp(enClassNameId, "set") == 0 || + std::strcmp(enClassNameId, "unordered_set") == 0 || + std::strcmp(enClassNameId, "multiset") == 0 || + std::strcmp(enClassNameId, "array") == 0) { + if (std::strcmp(nameId, "reference") == 0 || + std::strcmp(nameId, "const_reference") == 0) { + newType = clone->type(subst->apply(firstTemplParamName), 0); + } else if (std::strcmp(nameId, "iterator") == 0 || + std::strcmp(nameId, "reverse_iterator") == 0 || + std::strcmp(nameId, "const_reverse_iterator") == 0 || + std::strcmp(nameId, "const_iterator") == 0) { + newType = clone->type(subst->apply(firstTemplParamName), 0); + newType = FullySpecifiedType(clone->control()->pointerType(newType)); + } + } else if (std::strcmp(enClassNameId, "_Hash") == 0 || + std::strcmp(enClassNameId, "_Tree") == 0 ) { + if (std::strcmp(nameId, "iterator") == 0 || + std::strcmp(nameId, "reverse_iterator") == 0 || + std::strcmp(nameId, "const_reverse_iterator") == 0 || + std::strcmp(nameId, "const_iterator") == 0) { + FullySpecifiedType clonedType = clone->type(subst->apply(firstTemplParamName), 0); + if (NamedType *namedType = clonedType.type()->asNamedType()) { + if (const TemplateNameId * templateNameId = + namedType->name()->asTemplateNameId()) { + if (templateNameId->templateArgumentCount()) { + newType = clone->type(templateNameId->templateArgumentAt(0), 0); + newType = FullySpecifiedType(clone->control()->pointerType(newType)); + } + } + } + } + } + } + + if (newType.isValid()) + _type = newType; +} Declaration::~Declaration() { } diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 182eda1d59..37b9ce8b30 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -950,9 +950,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) foreach (const LookupItem &r, b->find(arrayAccessOp)) { Symbol *overload = r.declaration(); if (Function *funTy = overload->type()->asFunctionType()) { - if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType()) - // ### TODO: check the actual arguments - addResult(proto->returnType().simplified(), scope); + // ### TODO: check the actual arguments + addResult(funTy->returnType().simplified(), scope, b); } } diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 1fd80aad13..b494476351 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -2584,6 +2584,169 @@ void CppToolsPlugin::test_completion_data() " @\n" "}\n" ) << _("t.p->") << QStringList({"Foo", "bar"}); + + QTest::newRow("fix_code_completion_for_unique_ptr_operator_arrow") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct unique_ptr\n" + "{\n" + " typedef FOO pointer;\n" + " pointer operator->();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::unique_ptr<Foo> ptr;\n" + " @\n" + "}\n" + ) << _("ptr->") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_unique_ptr_method_get") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct unique_ptr\n" + "{\n" + " typedef FOO pointer;\n" + " pointer get();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::unique_ptr<Foo> ptr;\n" + " @\n" + "}\n" + ) << _("ptr.get()->") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_vector_method_at") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct vector\n" + "{\n" + " typedef FOO reference;\n" + " reference at(size_t i);\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::vector<Foo> v;\n" + " @\n" + "}\n" + ) << _("v.at(0).") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_vector_operator_square_brackets") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct vector\n" + "{\n" + " typedef FOO reference;\n" + " reference operator[](size_t i);\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::vector<Foo> v;\n" + " @\n" + "}\n" + ) << _("v[0].") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_list_method_front") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct list\n" + "{\n" + " typedef FOO reference;\n" + " reference front();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::list<Foo> l;\n" + " @\n" + "}\n" + ) << _("l.front().") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_queue_method_front") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct queue\n" + "{\n" + " typedef FOO reference;\n" + " reference front();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::queue<Foo> l;\n" + " @\n" + "}\n" + ) << _("l.front().") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_set_method_begin") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct set\n" + "{\n" + " typedef FOO iterator;\n" + " iterator begin();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::set<Foo> s;\n" + " @\n" + "}\n" + ) << _("s.begin()->") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_multiset_method_begin") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct multiset\n" + "{\n" + " typedef FOO iterator;\n" + " iterator begin();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::multiset<Foo> s;\n" + " @\n" + "}\n" + ) << _("s.begin()->") << QStringList({"Foo", "bar"}); + QTest::newRow("fix_code_completion_for_std_unordered_set_method_begin") << _( + "namespace std {\n" + "template<typename _Tp>\n" + "struct unordered_set\n" + "{\n" + " typedef FOO iterator;\n" + " iterator begin();\n" + "};\n" + "}\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " std::unordered_set<Foo> s;\n" + " @\n" + "}\n" + ) << _("s.begin()->") << QStringList({"Foo", "bar"}); } void CppToolsPlugin::test_completion_member_access_operator() |