Skip to content
Snippets Groups Projects
Commit 8b514657 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Added support to complete function-call operators.

parent 30f355da
No related branches found
No related tags found
No related merge requests found
...@@ -547,8 +547,36 @@ bool ResolveExpression::visit(TemplateIdAST *ast) ...@@ -547,8 +547,36 @@ bool ResolveExpression::visit(TemplateIdAST *ast)
return false; 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) bool ResolveExpression::visit(CallAST *ast)
{ {
ResolveClass resolveClass;
const QList<Result> baseResults = _results;
_results.clear();
// Compute the types of the actual arguments. // Compute the types of the actual arguments.
QList< QList<Result> > arguments; QList< QList<Result> > arguments;
for (ExpressionListAST *exprIt = ast->expression_list; exprIt; for (ExpressionListAST *exprIt = ast->expression_list; exprIt;
...@@ -556,30 +584,38 @@ bool ResolveExpression::visit(CallAST *ast) ...@@ -556,30 +584,38 @@ bool ResolveExpression::visit(CallAST *ast)
arguments.append(operator()(exprIt->expression)); arguments.append(operator()(exprIt->expression));
} }
QList<Result> baseResults = _results; const unsigned actualArgumentCount = arguments.count();
_results.clear();
foreach (Result p, baseResults) { Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
if (Function *funTy = p.first->asFunctionType()) {
unsigned minNumberArguments = 0; foreach (const Result &result, baseResults) {
for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) { FullySpecifiedType ty = result.first.simplified();
Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument(); Symbol *lastVisibleSymbol = result.second;
if (arg->hasInitializer())
break; if (NamedType *namedTy = ty->asNamedType()) {
} const QList<Symbol *> classObjectCandidates = resolveClass(namedTy->name(), result, _context);
const unsigned actualArgumentCount = arguments.count();
if (actualArgumentCount < minNumberArguments) { foreach (Symbol *classObject, classObjectCandidates) {
// not enough arguments. const QList<Result> overloads = resolveMember(functionCallOp, classObject->asClass(), namedTy->name());
} else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) {
// too many arguments. foreach (const Result &o, overloads) {
} else { FullySpecifiedType overloadTy = o.first.simplified();
p.first = funTy->returnType();
addResult(p); 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 // Constructor call
p.first = control()->namedType(classTy->name()); FullySpecifiedType ctorTy = control()->namedType(classTy->name());
addResult(p); addResult(ctorTy, lastVisibleSymbol);
} }
} }
......
...@@ -68,6 +68,8 @@ protected: ...@@ -68,6 +68,8 @@ protected:
void addResult(const Result &result); void addResult(const Result &result);
void addResults(const QList<Result> &results); void addResults(const QList<Result> &results);
bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
using ASTVisitor::visit; using ASTVisitor::visit;
virtual bool visit(ExpressionListAST *ast); virtual bool visit(ExpressionListAST *ast);
......
...@@ -857,7 +857,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) ...@@ -857,7 +857,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
} }
if (! resolvedTypes.isEmpty()) { if (! resolvedTypes.isEmpty()) {
if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(resolvedTypes)) { if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(resolvedTypes, context)) {
return m_startPosition; return m_startPosition;
} else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && } else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
...@@ -884,16 +884,19 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) ...@@ -884,16 +884,19 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
QTextCursor tc(edit->document()); QTextCursor tc(edit->document());
tc.setPosition(index); tc.setPosition(index);
QString baseExpression = expressionUnderCursor(tc);
const QString baseExpression = expressionUnderCursor(tc);
// Resolve the type of this expression // Resolve the type of this expression
QList<TypeOfExpression::Result> results = const QList<TypeOfExpression::Result> results =
typeOfExpression(baseExpression, thisDocument, lastVisibleSymbol, TypeOfExpression::Preprocess); typeOfExpression(baseExpression, thisDocument,
lastVisibleSymbol,
TypeOfExpression::Preprocess);
// If it's a class, add completions for the constructors // If it's a class, add completions for the constructors
foreach (const TypeOfExpression::Result &result, results) { foreach (const TypeOfExpression::Result &result, results) {
if (result.first->isClassType()) { if (result.first->isClassType()) {
if (completeConstructorOrFunction(results)) if (completeConstructorOrFunction(results, context))
return m_startPosition; return m_startPosition;
break; break;
} }
...@@ -905,12 +908,13 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) ...@@ -905,12 +908,13 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
return -1; return -1;
} }
bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results) bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpression::Result> &results,
const LookupContext &context)
{ {
QList<Function *> functions; QList<Function *> functions;
foreach (const TypeOfExpression::Result &result, results) { foreach (const TypeOfExpression::Result &result, results) {
FullySpecifiedType exprTy = result.first; FullySpecifiedType exprTy = result.first.simplified();
if (Class *klass = exprTy->asClassType()) { if (Class *klass = exprTy->asClassType()) {
Name *className = klass->name(); Name *className = klass->name();
...@@ -940,8 +944,8 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi ...@@ -940,8 +944,8 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
} }
if (functions.isEmpty()) { if (functions.isEmpty()) {
foreach (const TypeOfExpression::Result &p, results) { foreach (const TypeOfExpression::Result &result, results) {
FullySpecifiedType ty = p.first; FullySpecifiedType ty = result.first.simplified();
if (Function *fun = ty->asFunctionType()) { if (Function *fun = ty->asFunctionType()) {
...@@ -950,10 +954,6 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi ...@@ -950,10 +954,6 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
else if (! functions.isEmpty() && functions.first()->scope() != fun->scope()) else if (! functions.isEmpty() && functions.first()->scope() != fun->scope())
continue; // skip fun, it's an hidden declaration. continue; // skip fun, it's an hidden declaration.
Name *name = fun->name();
if (QualifiedNameId *q = fun->name()->asQualifiedNameId())
name = q->unqualifiedNameId();
bool newOverload = true; bool newOverload = true;
foreach (Function *f, functions) { foreach (Function *f, functions) {
...@@ -967,7 +967,35 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi ...@@ -967,7 +967,35 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
functions.append(fun); 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()) { if (! functions.isEmpty()) {
......
...@@ -113,7 +113,8 @@ private: ...@@ -113,7 +113,8 @@ private:
bool completeInclude(const QTextCursor &cursor); 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> &, bool completeMember(const QList<CPlusPlus::TypeOfExpression::Result> &,
const CPlusPlus::LookupContext &context); const CPlusPlus::LookupContext &context);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment