summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus/ResolveExpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/cplusplus/ResolveExpression.cpp')
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 9b8dceebd3..ba6952e7bf 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -738,11 +738,67 @@ ResolveExpression::resolveMember(Name *memberName, Class *klass,
}
+QList<ResolveExpression::Result>
+ResolveExpression::resolveMember(Name *memberName, ObjCClass *klass) const
+{
+ QList<Result> results;
+
+ if (!memberName || !klass)
+ return results;
+
+ QList<Scope *> scopes;
+ _context.expand(klass->members(), _context.visibleScopes(), &scopes);
+
+ QList<Symbol *> candidates = _context.resolve(memberName, scopes);
+
+ foreach (Symbol *candidate, candidates) {
+ FullySpecifiedType ty = candidate->type();
+
+ results.append(Result(ty, candidate));
+ }
+
+ return removeDuplicates(results);
+}
+
bool ResolveExpression::visit(PostIncrDecrAST *)
{
return false;
}
+bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
+{
+ QList<Result> receiverResults = operator()(ast->receiver_expression);
+
+ if (!receiverResults.isEmpty()) {
+ Result result = receiverResults.first();
+ FullySpecifiedType ty = result.first.simplified();
+ Name *klassName = 0;
+
+ if (const ObjCClass *classTy = ty->asObjCClassType()) {
+ // static access, e.g.:
+ // [NSObject description];
+ klassName = classTy->name();
+ } else if (const PointerType *ptrTy = ty->asPointerType()) {
+ const FullySpecifiedType pointeeTy = ptrTy->elementType();
+ if (pointeeTy && pointeeTy->isNamedType()) {
+ // dynamic access, e.g.:
+ // NSObject *obj = ...; [obj release];
+ klassName = pointeeTy->asNamedType()->name();
+ }
+ }
+
+ if (klassName&&ast->selector && ast->selector->selector_name) {
+ ResolveObjCClass resolveObjCClass;
+ QList<Symbol *> resolvedSymbols = resolveObjCClass(klassName, result, _context);
+ foreach (Symbol *resolvedSymbol, resolvedSymbols)
+ if (ObjCClass *klass = resolvedSymbol->asObjCClass())
+ _results.append(resolveMember(ast->selector->selector_name, klass));
+ }
+ }
+
+ return false;
+}
+
////////////////////////////////////////////////////////////////////////////////
ResolveClass::ResolveClass()
{ }
@@ -811,3 +867,35 @@ QList<Symbol *> ResolveClass::resolveClass(Name *name,
return resolvedSymbols;
}
+
+ResolveObjCClass::ResolveObjCClass()
+{}
+
+QList<Symbol *> ResolveObjCClass::operator ()(Name *name,
+ const ResolveExpression::Result &p,
+ const LookupContext &context)
+{
+ QList<Symbol *> resolvedSymbols;
+
+ const QList<Symbol *> candidates =
+ context.resolve(name, context.visibleScopes(p));
+
+ foreach (Symbol *candidate, candidates) {
+ if (ObjCClass *klass = candidate->asObjCClass()) {
+ if (resolvedSymbols.contains(klass))
+ continue; // we already know about `klass'
+ resolvedSymbols.append(klass);
+ } else if (candidate->isTypedef()) {
+ if (Declaration *decl = candidate->asDeclaration()) {
+ if (decl->type()->isObjCClassType()) {
+ ObjCClass *klass = decl->type()->asObjCClassType();
+ if (resolvedSymbols.contains(klass))
+ continue;
+ resolvedSymbols.append(klass);
+ }
+ }
+ }
+ }
+
+ return resolvedSymbols;
+}