summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2009-10-16 12:22:33 +0200
committerRoberto Raggi <roberto.raggi@nokia.com>2009-10-16 12:23:16 +0200
commit8b514657ccb686f51a54ea9c3ab07e8877cada15 (patch)
treee6597031e9168c611f9e4d1edf9be24ae9ded28f
parent30f355dac368c6ef181cd97a62e4972807147fa1 (diff)
downloadqt-creator-8b514657ccb686f51a54ea9c3ab07e8877cada15.tar.gz
Added support to complete function-call operators.
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp78
-rw-r--r--src/libs/cplusplus/ResolveExpression.h2
-rw-r--r--src/plugins/cpptools/cppcodecompletion.cpp54
-rw-r--r--src/plugins/cpptools/cppcodecompletion.h3
4 files changed, 102 insertions, 35 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 690961cb75..f31e42fbc9 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 033126e3c0..0e0b637c22 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 16bda30448..42cd69ff77 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 afe8a16821..f8c7664728 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);