From 8dc369bc2d631ec94cecfec542b5dd0ce8f20946 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Fri, 16 Oct 2009 11:08:06 +0200 Subject: [PATCH] Simplified member completion. Share code with ResolveExpression. --- src/libs/cplusplus/ResolveExpression.cpp | 18 ++- src/libs/cplusplus/ResolveExpression.h | 6 +- src/plugins/cpptools/cppcodecompletion.cpp | 147 ++++----------------- 3 files changed, 46 insertions(+), 125 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 23aa23a66d4..033d61aad86 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -647,7 +647,8 @@ bool ResolveExpression::visit(MemberAccessAST *ast) } QList<ResolveExpression::Result> -ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp) const +ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp, + bool *replacedDotOperator) const { QList<Result> results; @@ -715,6 +716,16 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a results.append(Result(elementTy, lastVisibleSymbol)); } } else if (accessOp == T_DOT) { + if (replacedDotOperator) { + if (PointerType *ptrTy = ty->asPointerType()) { + *replacedDotOperator = true; + ty = ptrTy->elementType().simplified(); + } else if (ArrayType *arrTy = ty->asArrayType()) { + *replacedDotOperator = true; + ty = arrTy->elementType().simplified(); + } + } + if (ty->isClassType() || ty->isNamedType()) results.append(Result(ty, lastVisibleSymbol)); @@ -734,12 +745,13 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a QList<ResolveExpression::Result> ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults, unsigned accessOp, - Name *memberName) const + Name *memberName, + bool *replacedDotOperator) const { ResolveClass resolveClass; QList<Result> results; - const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp); + const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp, replacedDotOperator); foreach (const Result &r, classObjectResults) { FullySpecifiedType ty = r.first; diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index fb00f9e23f6..8d6f321bf71 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -51,7 +51,8 @@ public: QList<Result> resolveMemberExpression(const QList<Result> &baseResults, unsigned accessOp, - Name *memberName) const; + Name *memberName, + bool *replacedDotOperator = 0) const; QList<Result> resolveMember(Name *memberName, Class *klass, Name *className = 0) const; @@ -65,7 +66,8 @@ public: QList<Result> resolveBaseExpression(const QList<Result> &baseResults, - int accessOp) const; + int accessOp, + bool *replacedDotOperator = 0) const; protected: QList<Result> switchResults(const QList<Result> &symbols); diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 0a30af6f78c..16bda304487 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -984,135 +984,42 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi return false; } -bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &results, +bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &baseResults, const LookupContext &context) { - if (results.isEmpty()) + if (baseResults.isEmpty()) return false; - TypeOfExpression::Result result = results.first(); - QList<Symbol *> classObjectCandidates; - - if (m_completionOperator == T_ARROW) { - FullySpecifiedType ty = result.first.simplified(); - - if (Class *classTy = ty->asClassType()) { - Symbol *symbol = result.second; - if (symbol && ! symbol->isClass()) - classObjectCandidates.append(classTy); - } else if (NamedType *namedTy = ty->asNamedType()) { - // ### This code is pretty slow. - const QList<Symbol *> candidates = context.resolve(namedTy->name()); - foreach (Symbol *candidate, candidates) { - if (candidate->isTypedef()) { - ty = candidate->type(); - const ResolveExpression::Result r(ty, candidate); - result = r; - break; - } - } - } - - if (NamedType *namedTy = ty->asNamedType()) { - ResolveExpression resolveExpression(context); - ResolveClass resolveClass; - - const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, context); - foreach (Symbol *classObject, candidates) { - const QList<TypeOfExpression::Result> overloads = - resolveExpression.resolveArrowOperator(result, namedTy, - classObject->asClass()); - - foreach (TypeOfExpression::Result r, overloads) { - FullySpecifiedType ty = r.first; - Function *funTy = ty->asFunctionType(); - if (! funTy) - continue; - - ty = funTy->returnType().simplified(); - - if (PointerType *ptrTy = ty->asPointerType()) { - FullySpecifiedType elementTy = ptrTy->elementType().simplified(); - if (NamedType *namedTy = elementTy->asNamedType()) { - const QList<Symbol *> classes = - resolveClass(namedTy->name(), result, context); - - foreach (Symbol *c, classes) { - if (! classObjectCandidates.contains(c)) - classObjectCandidates.append(c); - } - } - } - } - } - } else if (PointerType *ptrTy = ty->asPointerType()) { - FullySpecifiedType elementTy = ptrTy->elementType().simplified(); - if (NamedType *namedTy = elementTy->asNamedType()) { - ResolveClass resolveClass; - - const QList<Symbol *> classes = resolveClass(namedTy->name(), result, - context); - - foreach (Symbol *c, classes) { - if (! classObjectCandidates.contains(c)) - classObjectCandidates.append(c); - } - } else if (Class *classTy = elementTy->asClassType()) { - // typedef struct { int x } *Ptr; - // Ptr p; - // p-> - classObjectCandidates.append(classTy); - } - } - } else if (m_completionOperator == T_DOT) { - FullySpecifiedType ty = result.first.simplified(); - - NamedType *namedTy = 0; + ResolveExpression resolveExpression(context); + ResolveClass resolveClass; - if (ArrayType *arrayTy = ty->asArrayType()) { - // Replace . with [0]. when `ty' is an array type. - FullySpecifiedType elementTy = arrayTy->elementType().simplified(); + bool replacedDotOperator = false; + const QList<TypeOfExpression::Result> classObjectResults = + resolveExpression.resolveBaseExpression(baseResults, + m_completionOperator, + &replacedDotOperator); + + if (replacedDotOperator) { + // Replace . with -> + int length = m_editor->position() - m_startPosition + 1; + m_editor->setCurPos(m_startPosition - 1); + m_editor->replace(length, QLatin1String("->")); + ++m_startPosition; + } - if (elementTy->isNamedType() || elementTy->isPointerType()) { - ty = elementTy; + QList<Symbol *> classObjectCandidates; + foreach (const TypeOfExpression::Result &r, classObjectResults) { + FullySpecifiedType ty = r.first.simplified(); - const int length = m_editor->position() - m_startPosition + 1; - m_editor->setCurPos(m_startPosition - 1); - m_editor->replace(length, QLatin1String("[0].")); - m_startPosition += 3; - } - } + if (Class *klass = ty->asClassType()) + classObjectCandidates.append(klass); - if (PointerType *ptrTy = ty->asPointerType()) { - if (ptrTy->elementType()->isNamedType()) { - // Replace . with -> - int length = m_editor->position() - m_startPosition + 1; - m_editor->setCurPos(m_startPosition - 1); - m_editor->replace(length, QLatin1String("->")); - ++m_startPosition; - namedTy = ptrTy->elementType()->asNamedType(); - } - } 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->asFunctionType(); - if (fun && fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope())) - namedTy = fun->returnType()->asNamedType(); - } - } + else if (NamedType *namedTy = ty->asNamedType()) { + Name *className = namedTy->name(); + const QList<Symbol *> classes = resolveClass(className, r, context); - if (namedTy) { - ResolveClass resolveClass; - const QList<Symbol *> symbols = resolveClass(namedTy->name(), result, - context); - foreach (Symbol *symbol, symbols) { - if (classObjectCandidates.contains(symbol)) - continue; - if (Class *klass = symbol->asClass()) + foreach (Symbol *c, classes) { + if (Class *klass = c->asClass()) classObjectCandidates.append(klass); } } -- GitLab