diff options
Diffstat (limited to 'src/plugins/cpptools/cppcodecompletion.cpp')
| -rw-r--r-- | src/plugins/cpptools/cppcodecompletion.cpp | 132 |
1 files changed, 90 insertions, 42 deletions
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index bca1d576e9..aef68ee6d3 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -432,7 +432,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) return -1; m_editor = editor; - m_startPosition = findStartOfName(editor); + m_startPosition = findStartOfName(); m_completionOperator = T_EOF_SYMBOL; int endOfOperator = m_startPosition; @@ -512,7 +512,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) context = typeOfExpression.lookupContext(); } - if (! resolvedTypes.isEmpty()) { + if (! resolvedTypes.isEmpty() && resolvedTypes.first().first) { FullySpecifiedType exprTy = resolvedTypes.first().first; if (exprTy->isReferenceType()) @@ -520,7 +520,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) if (m_completionOperator == T_LPAREN && completeFunction(exprTy, resolvedTypes, context)) { return m_startPosition; - } if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && + } else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && completeMember(resolvedTypes, context)) { return m_startPosition; } else if (m_completionOperator == T_COLON_COLON && completeScope(resolvedTypes, context)) { @@ -531,6 +531,32 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) return m_startPosition; } } + + if (m_completionOperator == T_LPAREN) { + // Find the expression that precedes the current name + int index = endOfExpression; + while (m_editor->characterAt(index - 1).isSpace()) + --index; + index = findStartOfName(index); + + QTextCursor tc(edit->document()); + tc.setPosition(index); + QString baseExpression = expressionUnderCursor(tc); + + // Resolve the type of this expression + QList<TypeOfExpression::Result> results = + typeOfExpression(baseExpression, thisDocument, symbol, TypeOfExpression::Preprocess); + + // If it's a class, add completions for the constructors + foreach (const TypeOfExpression::Result &result, results) { + if (result.first->isClassType()) { + FullySpecifiedType exprTy = result.first; + if (completeConstructors(exprTy->asClassType())) + return m_startPosition; + break; + } + } + } } // nothing to do. @@ -541,30 +567,18 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, const QList<TypeOfExpression::Result> &resolvedTypes, const LookupContext &) { - ConvertToCompletionItem toCompletionItem(this); - Overview o; - o.setShowReturnTypes(true); - o.setShowArgumentNames(true); - - if (Class *klass = exprTy->asClass()) { - for (unsigned i = 0; i < klass->memberCount(); ++i) { - Symbol *member = klass->memberAt(i); - if (! member->type()->isFunction()) - continue; - else if (! member->identity()) - continue; - else if (! member->identity()->isEqualTo(klass->identity())) - continue; - if (TextEditor::CompletionItem item = toCompletionItem(member)) { - item.m_text = o(member->type(), member->name()); - m_completions.append(item); - } - } + if (Class *klass = exprTy->asClassType()) { + completeConstructors(klass); } else { + ConvertToCompletionItem toCompletionItem(this); + Overview o; + o.setShowReturnTypes(true); + o.setShowArgumentNames(true); + QSet<QString> signatures; foreach (TypeOfExpression::Result p, resolvedTypes) { FullySpecifiedType ty = p.first; - if (Function *fun = ty->asFunction()) { + if (Function *fun = ty->asFunctionType()) { if (TextEditor::CompletionItem item = toCompletionItem(fun)) { QString signature; signature += overview.prettyName(fun->name()); @@ -598,7 +612,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); - if (Class *classTy = ty->asClass()) { + if (Class *classTy = ty->asClassType()) { Symbol *symbol = result.second; if (symbol && ! symbol->isClass()) classObjectCandidates.append(classTy); @@ -627,7 +641,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re foreach (TypeOfExpression::Result r, overloads) { FullySpecifiedType ty = r.first; - Function *funTy = ty->asFunction(); + Function *funTy = ty->asFunctionType(); if (! funTy) continue; @@ -660,7 +674,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re if (! classObjectCandidates.contains(c)) classObjectCandidates.append(c); } - } else if (Class *classTy = ptrTy->elementType()->asClass()) { + } else if (Class *classTy = ptrTy->elementType()->asClassType()) { // typedef struct { int x } *Ptr; // Ptr p; // p-> @@ -701,14 +715,14 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re ++m_startPosition; namedTy = ptrTy->elementType()->asNamedType(); } - } else if (Class *classTy = ty->asClass()) { + } else if (Class *classTy = ty->asClassType()) { Symbol *symbol = result.second; if (symbol && ! symbol->isClass()) classObjectCandidates.append(classTy); } else { namedTy = ty->asNamedType(); if (! namedTy) { - Function *fun = ty->asFunction(); + Function *fun = ty->asFunctionType(); if (fun && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope())) namedTy = fun->returnType()->asNamedType(); } @@ -745,24 +759,24 @@ bool CppCodeCompletion::completeScope(const QList<TypeOfExpression::Result> &res foreach (result, results) { FullySpecifiedType ty = result.first; - if (ty->isClass() || ty->isNamespace()) + if (ty->isClassType() || ty->isNamespaceType()) break; } FullySpecifiedType exprTy = result.first; if (! exprTy) { return false; - } else if (exprTy->asNamespace()) { + } else if (exprTy->isNamespaceType()) { QList<Symbol *> candidates; foreach (TypeOfExpression::Result p, results) { - if (Namespace *ns = p.first->asNamespace()) + if (Namespace *ns = p.first->asNamespaceType()) candidates.append(ns); } completeNamespace(candidates, context); - } else if (exprTy->isClass()) { + } else if (exprTy->isClassType()) { QList<Symbol *> candidates; foreach (TypeOfExpression::Result p, results) { - if (Class *k = p.first->asClass()) + if (Class *k = p.first->asClassType()) candidates.append(k); } completeClass(candidates, context); @@ -873,6 +887,33 @@ void CppCodeCompletion::completeClass(const QList<Symbol *> &candidates, } } +bool CppCodeCompletion::completeConstructors(Class *klass) +{ + ConvertToCompletionItem toCompletionItem(this); + Overview o; + o.setShowReturnTypes(true); + o.setShowArgumentNames(true); + + for (unsigned i = 0; i < klass->memberCount(); ++i) { + Symbol *member = klass->memberAt(i); + FullySpecifiedType memberTy = member->type(); + if (! memberTy) + continue; + else if (! memberTy->isFunctionType()) + continue; + else if (! member->identity()) + continue; + else if (! member->identity()->isEqualTo(klass->identity())) + continue; + if (TextEditor::CompletionItem item = toCompletionItem(member)) { + item.m_text = o(member->type(), member->name()); + m_completions.append(item); + } + } + + return ! m_completions.isEmpty(); +} + bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, const QList<TypeOfExpression::Result> &results, const LookupContext &context, @@ -892,8 +933,12 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, QSet<QString> signatures; foreach (TypeOfExpression::Result p, results) { FullySpecifiedType ty = p.first; + if (! ty) + continue; + if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); + if (PointerType *ptrTy = ty->asPointerType()) ty = ptrTy->elementType(); else @@ -921,7 +966,7 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, for (unsigned i = 0; i < scope->symbolCount(); ++i) { Symbol *member = scope->symbolAt(i); - Function *fun = member->type()->asFunction(); + Function *fun = member->type()->asFunctionType(); if (! fun) continue; if (wantSignals && ! fun->isSignal()) @@ -1037,7 +1082,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) if (m_completionOperator == T_LPAREN) { if (symbol) { - Function *function = symbol->type()->asFunction(); + Function *function = symbol->type()->asFunctionType(); QTC_ASSERT(function, return); m_functionArgumentWidget = new FunctionArgumentWidget(); @@ -1056,8 +1101,8 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) //qDebug() << "current symbol:" << overview.prettyName(symbol->name()) //<< overview.prettyType(symbol->type()); - if (m_autoInsertBraces && symbol) { - if (Function *function = symbol->type()->asFunction()) { + if (m_autoInsertBraces && symbol && symbol->type()) { + if (Function *function = symbol->type()->asFunctionType()) { // If the member is a function, automatically place the opening parenthesis, // except when it might take template parameters. const bool hasReturnType = function->returnType().isValid() || @@ -1075,13 +1120,15 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) toInsert.append(QLatin1Char('(')); // If the function takes no arguments, automatically place the closing parenthesis - if (function->argumentCount() == 0 || (function->argumentCount() == 1 && + if (function->argumentCount() == 0 || (function->argumentCount() == 1 && + function->argumentAt(0)->type() && function->argumentAt(0)->type()->isVoidType())) { toInsert.append(QLatin1Char(')')); // If the function doesn't return anything, automatically place the semicolon, // unless we're doing a scope completion (then it might be function definition). - if (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON) { + FullySpecifiedType retTy = function->returnType(); + if (retTy && retTy->isVoidType() && m_completionOperator != T_COLON_COLON) { toInsert.append(QLatin1Char(';')); } } @@ -1135,14 +1182,15 @@ void CppCodeCompletion::cleanup() typeOfExpression.setSnapshot(Snapshot()); } -int CppCodeCompletion::findStartOfName(const TextEditor::ITextEditor *editor) +int CppCodeCompletion::findStartOfName(int pos) const { - int pos = editor->position(); + if (pos == -1) + pos = m_editor->position(); QChar chr; // Skip to the start of a name do { - chr = editor->characterAt(--pos); + chr = m_editor->characterAt(--pos); } while (chr.isLetterOrNumber() || chr == QLatin1Char('_')); return pos + 1; |
