summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus/ResolveExpression.cpp
diff options
context:
space:
mode:
authorPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>2012-11-29 14:42:47 +0100
committerNikolai Kosjar <nikolai.kosjar@digia.com>2012-12-05 11:39:18 +0100
commit6b67f24865dba2f6712967d5af70024339228e64 (patch)
treeffc557344156886a63bf356f116bc455c25a02ce /src/libs/cplusplus/ResolveExpression.cpp
parent0b3eb65fc93c06e78fd90fee27b75b1d9cf630c1 (diff)
downloadqt-creator-6b67f24865dba2f6712967d5af70024339228e64.tar.gz
C++: Fix code completion for operator ->
Fix code completion for operator '->' when returned value is a pointer of typedef(e.g.:std::auto_ptr). Included unit test. Task-number: QTCREATORBUG-629 Change-Id: I36b53a3f80b3c99d52791e18ad1244923c1373f6 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
Diffstat (limited to 'src/libs/cplusplus/ResolveExpression.cpp')
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp104
1 files changed, 68 insertions, 36 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 48d734763b..eaa53f738f 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -828,43 +828,71 @@ ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &origina
return binding;
}
-static void resolveTypedefs(const LookupContext &context,
- FullySpecifiedType *type,
- Scope **scope, ClassOrNamespace *binding)
+class TypedefsResolver
{
- QSet<Symbol *> visited;
- while (NamedType *namedTy = (*type)->asNamedType()) {
+public:
+ TypedefsResolver(const LookupContext &context) : _context(context) {}
+ void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding)
+ {
+ QSet<Symbol *> visited;
+ while (NamedType *namedTy = getNamedType(*type)) {
+ QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, binding);
+
+#ifdef DEBUG_LOOKUP
+ qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
+#endif // DEBUG_LOOKUP
- // check if namedTy->name() resolves to a typedef
+ if (!findTypedef(namedTypeItems, type, scope, visited))
+ break;
+ }
+ }
+
+private:
+ NamedType *getNamedType(FullySpecifiedType& type)
+ {
+ NamedType *namedTy = type->asNamedType();
+ if (! namedTy) {
+ if (PointerType *pointerTy = type->asPointerType())
+ namedTy = pointerTy->elementType()->asNamedType();
+ }
+ return namedTy;
+ }
+
+ QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope, ClassOrNamespace *binding)
+ {
QList<LookupItem> namedTypeItems;
if (binding)
- namedTypeItems = binding->lookup(namedTy->name());
- if (ClassOrNamespace *scopeCon = context.lookupType(*scope))
- namedTypeItems += scopeCon->lookup(namedTy->name());
+ namedTypeItems = binding->lookup(name);
+ if (ClassOrNamespace *scopeCon = _context.lookupType(scope))
+ namedTypeItems += scopeCon->lookup(name);
-#ifdef DEBUG_LOOKUP
- qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
-#endif // DEBUG_LOOKUP
+ return namedTypeItems;
+ }
+ bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
+ Scope **scope, QSet<Symbol *>& visited)
+ {
bool foundTypedef = false;
foreach (const LookupItem &it, namedTypeItems) {
- if (it.declaration() && it.declaration()->isTypedef()) {
- if (visited.contains(it.declaration()))
+ Symbol *declaration = it.declaration();
+ if (declaration && declaration->isTypedef()) {
+ if (visited.contains(declaration))
break;
- visited.insert(it.declaration());
+ visited.insert(declaration);
// continue working with the typedefed type and scope
- *type = it.declaration()->type();
+ *type = declaration->type();
*scope = it.scope();
foundTypedef = true;
break;
}
}
- if (!foundTypedef)
- break;
+ return foundTypedef;
}
-}
+
+ const LookupContext &_context;
+};
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
int accessOp,
@@ -875,6 +903,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
int i = 0;
Overview oo;
#endif // DEBUG_LOOKUP
+ TypedefsResolver typedefsResolver(_context);
foreach (const LookupItem &r, baseResults) {
FullySpecifiedType ty = r.type().simplified();
@@ -885,7 +914,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
qDebug()<<"- before typedef resolving we have:"<<oo(ty);
#endif // DEBUG_LOOKUP
- resolveTypedefs(_context, &ty, &scope, r.binding());
+ typedefsResolver.resolve(&ty, &scope, r.binding());
#ifdef DEBUG_LOOKUP
qDebug()<<"- after typedef resolving:"<<oo(ty);
@@ -913,30 +942,33 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
FullySpecifiedType retTy = instantiatedFunction->returnType().simplified();
- resolveTypedefs(_context, &retTy, &functionScope, r.binding());
+ typedefsResolver.resolve(&retTy, &functionScope, r.binding());
- if (PointerType *ptrTy = retTy->asPointerType()) {
- if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), functionScope))
- return retBinding;
+ if (! retTy->isPointerType() && ! retTy->isNamedType())
+ continue;
- if (scope != functionScope) {
- if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
- return retBinding;
- }
+ if (PointerType *ptrTy = retTy->asPointerType())
+ retTy = ptrTy->elementType();
- if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
- foreach (Symbol *originSymbol, origin->symbols()) {
- Scope *originScope = originSymbol->asScope();
- if (originScope && originScope != scope && originScope != functionScope) {
- if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), originScope))
- return retBinding;
- }
+ if (ClassOrNamespace *retBinding = findClass(retTy, functionScope))
+ return retBinding;
+
+ if (scope != functionScope) {
+ if (ClassOrNamespace *retBinding = findClass(retTy, scope))
+ return retBinding;
+ }
+
+ if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
+ foreach (Symbol *originSymbol, origin->symbols()) {
+ Scope *originScope = originSymbol->asScope();
+ if (originScope && originScope != scope && originScope != functionScope) {
+ if (ClassOrNamespace *retBinding = findClass(retTy, originScope))
+ return retBinding;
}
}
}
}
}
-
}
} else if (accessOp == T_DOT) {
if (replacedDotOperator) {