diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 690961cb7529d93f5f581a33ead3e6269cd90b82..f31e42fbc923237504edc01572d6a8f742c6626c 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -547,8 +547,36 @@ bool ResolveExpression::visit(TemplateIdAST *ast) return false; } +bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const +{ + unsigned minNumberArguments = 0; + + for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) { + Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument(); + + if (arg->hasInitializer()) + break; + } + + if (actualArgumentCount < minNumberArguments) { + // not enough arguments. + return false; + + } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) { + // too many arguments. + return false; + } + + return true; +} + bool ResolveExpression::visit(CallAST *ast) { + ResolveClass resolveClass; + + const QList<Result> baseResults = _results; + _results.clear(); + // Compute the types of the actual arguments. QList< QList<Result> > arguments; for (ExpressionListAST *exprIt = ast->expression_list; exprIt; @@ -556,30 +584,38 @@ bool ResolveExpression::visit(CallAST *ast) arguments.append(operator()(exprIt->expression)); } - QList<Result> baseResults = _results; - _results.clear(); + const unsigned actualArgumentCount = arguments.count(); - foreach (Result p, baseResults) { - if (Function *funTy = p.first->asFunctionType()) { - unsigned minNumberArguments = 0; - for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) { - Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument(); - if (arg->hasInitializer()) - break; - } - const unsigned actualArgumentCount = arguments.count(); - if (actualArgumentCount < minNumberArguments) { - // not enough arguments. - } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) { - // too many arguments. - } else { - p.first = funTy->returnType(); - addResult(p); + Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp); + + foreach (const Result &result, baseResults) { + FullySpecifiedType ty = result.first.simplified(); + Symbol *lastVisibleSymbol = result.second; + + if (NamedType *namedTy = ty->asNamedType()) { + const QList<Symbol *> classObjectCandidates = resolveClass(namedTy->name(), result, _context); + + foreach (Symbol *classObject, classObjectCandidates) { + const QList<Result> overloads = resolveMember(functionCallOp, classObject->asClass(), namedTy->name()); + + foreach (const Result &o, overloads) { + FullySpecifiedType overloadTy = o.first.simplified(); + + if (Function *funTy = overloadTy->asFunctionType()) { + if (maybeValidPrototype(funTy, actualArgumentCount)) + addResult(funTy->returnType().simplified(), lastVisibleSymbol); + } + } } - } else if (Class *classTy = p.first->asClassType()) { + + } else if (Function *funTy = ty->asFunctionType()) { + if (maybeValidPrototype(funTy, actualArgumentCount)) + addResult(funTy->returnType().simplified(), lastVisibleSymbol); + + } else if (Class *classTy = ty->asClassType()) { // Constructor call - p.first = control()->namedType(classTy->name()); - addResult(p); + FullySpecifiedType ctorTy = control()->namedType(classTy->name()); + addResult(ctorTy, lastVisibleSymbol); } } diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 033126e3c0d1f3e95c213170e984977d2c0180bd..0e0b637c22812672ba45abcc6914e6a284396859 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -68,6 +68,8 @@ protected: void addResult(const Result &result); void addResults(const QList<Result> &results); + bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const; + using ASTVisitor::visit; virtual bool visit(ExpressionListAST *ast); diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 16bda3044874afe37252ef34e02a6c67bcf6c366..42cd69ff77b617306641d07f5c25e6519f9af1fb 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -857,7 +857,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) } if (! resolvedTypes.isEmpty()) { - if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(resolvedTypes)) { + if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(resolvedTypes, context)) { return m_startPosition; } else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && @@ -884,16 +884,19 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) QTextCursor tc(edit->document()); tc.setPosition(index); - QString baseExpression = expressionUnderCursor(tc); + + const QString baseExpression = expressionUnderCursor(tc); // Resolve the type of this expression - QList<TypeOfExpression::Result> results = - typeOfExpression(baseExpression, thisDocument, lastVisibleSymbol, TypeOfExpression::Preprocess); + const QList<TypeOfExpression::Result> results = + typeOfExpression(baseExpression, thisDocument, + lastVisibleSymbol, + TypeOfExpression::Preprocess); // If it's a class, add completions for the constructors foreach (const TypeOfExpression::Result &result, results) { if (result.first->isClassType()) { - if (completeConstructorOrFunction(results)) + if (completeConstructorOrFunction(results, context)) return m_startPosition; break; } @@ -905,12 +908,13 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) return -1; } -bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results) +bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results, + const LookupContext &context) { QList<Function *> functions; foreach (const TypeOfExpression::Result &result, results) { - FullySpecifiedType exprTy = result.first; + FullySpecifiedType exprTy = result.first.simplified(); if (Class *klass = exprTy->asClassType()) { Name *className = klass->name(); @@ -940,8 +944,8 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi } if (functions.isEmpty()) { - foreach (const TypeOfExpression::Result &p, results) { - FullySpecifiedType ty = p.first; + foreach (const TypeOfExpression::Result &result, results) { + FullySpecifiedType ty = result.first.simplified(); if (Function *fun = ty->asFunctionType()) { @@ -950,10 +954,6 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi else if (! functions.isEmpty() && functions.first()->scope() != fun->scope()) continue; // skip fun, it's an hidden declaration. - Name *name = fun->name(); - if (QualifiedNameId *q = fun->name()->asQualifiedNameId()) - name = q->unqualifiedNameId(); - bool newOverload = true; foreach (Function *f, functions) { @@ -967,7 +967,35 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi functions.append(fun); } } + } + + if (functions.isEmpty()) { + ResolveExpression resolveExpression(context); + ResolveClass resolveClass; + Name *functionCallOp = context.control()->operatorNameId(OperatorNameId::FunctionCallOp); + + foreach (const TypeOfExpression::Result &result, results) { + FullySpecifiedType ty = result.first.simplified(); + + if (NamedType *namedTy = ty->asNamedType()) { + const QList<Symbol *> classObjectCandidates = resolveClass(namedTy->name(), result, context); + foreach (Symbol *classObjectCandidate, classObjectCandidates) { + if (Class *klass = classObjectCandidate->asClass()) { + const QList<TypeOfExpression::Result> overloads = + resolveExpression.resolveMember(functionCallOp, klass, + namedTy->name()); + + foreach (const TypeOfExpression::Result &overloadResult, overloads) { + FullySpecifiedType overloadTy = overloadResult.first.simplified(); + + if (Function *funTy = overloadTy->asFunctionType()) + functions.append(funTy); + } + } + } + } + } } if (! functions.isEmpty()) { diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index afe8a1682153219f006b6f7742e2397aad506445..f8c7664728b2946c1eda6e958123b334f4eabbfe 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -113,7 +113,8 @@ private: bool completeInclude(const QTextCursor &cursor); - bool completeConstructorOrFunction(const QList<CPlusPlus::TypeOfExpression::Result> &); + bool completeConstructorOrFunction(const QList<CPlusPlus::TypeOfExpression::Result> &, + const CPlusPlus::LookupContext &); bool completeMember(const QList<CPlusPlus::TypeOfExpression::Result> &, const CPlusPlus::LookupContext &context);