diff options
Diffstat (limited to 'src/libs/cplusplus')
-rw-r--r-- | src/libs/cplusplus/BackwardsScanner.cpp | 1 | ||||
-rw-r--r-- | src/libs/cplusplus/ExpressionUnderCursor.cpp | 2 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 71 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupContext.h | 24 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 88 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.h | 15 |
6 files changed, 198 insertions, 3 deletions
diff --git a/src/libs/cplusplus/BackwardsScanner.cpp b/src/libs/cplusplus/BackwardsScanner.cpp index 7f1f6cdfe6..46fb15efe4 100644 --- a/src/libs/cplusplus/BackwardsScanner.cpp +++ b/src/libs/cplusplus/BackwardsScanner.cpp @@ -40,6 +40,7 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf { _tokenize.setQtMocRunEnabled(true); _tokenize.setSkipComments(true); + _tokenize.setObjCEnabled(true); _text = _block.text().left(cursor.position() - cursor.block().position()); if (! suffix.isEmpty()) diff --git a/src/libs/cplusplus/ExpressionUnderCursor.cpp b/src/libs/cplusplus/ExpressionUnderCursor.cpp index 995eeace37..67980ce4e1 100644 --- a/src/libs/cplusplus/ExpressionUnderCursor.cpp +++ b/src/libs/cplusplus/ExpressionUnderCursor.cpp @@ -106,6 +106,8 @@ int ExpressionUnderCursor::startOfExpression_helper(BackwardsScanner &tk, int in return startOfExpression(tk, index - 2); } else if (tk[index - 2].is(T_DOT_STAR) || tk[index - 2].is(T_ARROW_STAR)) { return startOfExpression(tk, index - 2); +// } else if (tk[index - 2].is(T_IDENTIFIER) && tk[index - 3].is(T_LBRACKET)) { +// return index - 3; } return index - 1; } else if (tk[index - 1].is(T_RPAREN)) { diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 4d3ed93275..653d86b0d0 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -89,8 +89,10 @@ bool LookupContext::maybeValidSymbol(Symbol *symbol, ResolveMode mode, const QList<Symbol *> &candidates) { - if (((mode & ResolveNamespace) && symbol->isNamespace()) || - ((mode & ResolveClass) && symbol->isClass()) || + if (((mode & ResolveNamespace) && symbol->isNamespace()) || + ((mode & ResolveClass) && symbol->isClass()) || + ((mode & ResolveObjCClass) && symbol->isObjCClass()) || + ((mode & ResolveObjCProtocol) && symbol->isObjCProtocol()) || (mode & ResolveSymbol)) { return ! candidates.contains(symbol); } @@ -527,6 +529,69 @@ void LookupContext::expandObjCMethod(ObjCMethod *method, expandedScopes->append(method->arguments()); } +void LookupContext::expandObjCClass(ObjCClass *klass, + const QList<Scope *> &visibleScopes, + QList<Scope *> *expandedScopes) const +{ + {// expand other @interfaces, @implementations and categories for this class: + const QList<Symbol *> classList = resolveObjCClass(klass->name(), visibleScopes); + foreach (Symbol *otherClass, classList) { + if (otherClass == klass) + continue; + expand(otherClass->asObjCClass()->members(), visibleScopes, expandedScopes); + } + } + + // expand definitions in the currect class: + for (unsigned i = 0; i < klass->memberCount(); ++i) { + Symbol *symbol = klass->memberAt(i); + if (Class *nestedClass = symbol->asClass()) { + if (! nestedClass->name()) { + expand(nestedClass->members(), visibleScopes, expandedScopes); + } + } else if (Enum *e = symbol->asEnum()) { + expand(e->members(), visibleScopes, expandedScopes); + } + } + + // expand the base class: + if (ObjCBaseClass *baseClass = klass->baseClass()) { + Name *baseClassName = baseClass->name(); + const QList<Symbol *> baseClassCandidates = resolveObjCClass(baseClassName, + visibleScopes); + + for (int j = 0; j < baseClassCandidates.size(); ++j) { + if (ObjCClass *baseClassSymbol = baseClassCandidates.at(j)->asObjCClass()) + expand(baseClassSymbol->members(), visibleScopes, expandedScopes); + } + } + + // expand the protocols: + for (unsigned i = 0; i < klass->protocolCount(); ++i) { + Name *protocolName = klass->protocolAt(i)->name(); + const QList<Symbol *> protocolCandidates = resolveObjCProtocol(protocolName, visibleScopes); + for (int j = 0; j < protocolCandidates.size(); ++j) { + if (ObjCProtocol *protocolSymbol = protocolCandidates.at(j)->asObjCProtocol()) + expandObjCProtocol(protocolSymbol, visibleScopes, expandedScopes); + } + } +} + +void LookupContext::expandObjCProtocol(ObjCProtocol *protocol, const QList<Scope *> &visibleScopes, QList<Scope *> *expandedScopes) const +{ + // First expand the protocol itself + expand(protocol->members(), visibleScopes, expandedScopes); + + // Then do the same for any incorporated protocol + for (unsigned i = 0; i < protocol->protocolCount(); ++i) { + ObjCBaseProtocol *baseProtocol = protocol->protocolAt(i); + const QList<Symbol *> protocolList = resolveObjCProtocol(baseProtocol->name(), visibleScopes); + foreach (Symbol *symbol, protocolList) + if (ObjCProtocol *protocolSymbol = symbol->asObjCProtocol()) + expandObjCProtocol(protocolSymbol, visibleScopes, expandedScopes); + } +} + void LookupContext::expand(Scope *scope, const QList<Scope *> &visibleScopes, QList<Scope *> *expandedScopes) const @@ -546,6 +611,8 @@ void LookupContext::expand(Scope *scope, expandFunction(fun, visibleScopes, expandedScopes); } else if (ObjCMethod *meth = scope->owner()->asObjCMethod()) { expandObjCMethod(meth, visibleScopes, expandedScopes); + } else if (ObjCClass *objcKlass = scope->owner()->asObjCClass()) { + expandObjCClass(objcKlass, visibleScopes, expandedScopes); } } diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index e9d84c83ae..6a69b3330b 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -75,12 +75,20 @@ public: QList<Symbol *> resolveClassOrNamespace(Name *name) const { return resolveClassOrNamespace(name, visibleScopes()); } + QList<Symbol *> resolveObjCClass(Name *name) const + { return resolveObjCClass(name, visibleScopes()); } + + QList<Symbol *> resolveObjCProtocol(Name *name) const + { return resolveObjCProtocol(name, visibleScopes()); } + enum ResolveMode { ResolveSymbol = 0x01, ResolveClass = 0x02, ResolveNamespace = 0x04, ResolveClassOrNamespace = ResolveClass | ResolveNamespace, - ResolveAll = ResolveSymbol | ResolveClassOrNamespace + ResolveObjCClass = 0x08, + ResolveObjCProtocol = 0x10, + ResolveAll = ResolveSymbol | ResolveClassOrNamespace | ResolveObjCClass | ResolveObjCProtocol }; QList<Symbol *> resolve(Name *name, const QList<Scope *> &visibleScopes, @@ -95,6 +103,12 @@ public: QList<Symbol *> resolveClassOrNamespace(Name *name, const QList<Scope *> &visibleScopes) const { return resolve(name, visibleScopes, ResolveClassOrNamespace); } + QList<Symbol *> resolveObjCClass(Name *name, const QList<Scope *> &visibleScopes) const + { return resolve(name, visibleScopes, ResolveObjCClass); } + + QList<Symbol *> resolveObjCProtocol(Name *name, const QList<Scope *> &visibleScopes) const + { return resolve(name, visibleScopes, ResolveObjCProtocol); } + QList<Scope *> visibleScopes() const { return _visibleScopes; } @@ -128,6 +142,14 @@ public: const QList<Scope *> &visibleScopes, QList<Scope *> *expandedScopes) const; + void expandObjCClass(ObjCClass *klass, + const QList<Scope *> &visibleScopes, + QList<Scope *> *expandedScopes) const; + + void expandObjCProtocol(ObjCProtocol *protocol, + const QList<Scope *> &visibleScopes, + QList<Scope *> *expandedScopes) const; + void expandEnumOrAnonymousSymbol(ScopedSymbol *scopedSymbol, QList<Scope *> *expandedScopes) const; 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; +} diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 34541e9f45..adda2716c3 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -61,6 +61,8 @@ public: QList<Result> resolveMember(Name *memberName, Class *klass, Name *className = 0) const; + QList<Result> resolveMember(Name *memberName, ObjCClass *klass) const; + protected: QList<Result> switchResults(const QList<Result> &symbols); @@ -109,6 +111,9 @@ protected: virtual bool visit(PostIncrDecrAST *ast); virtual bool visit(MemberAccessAST *ast); + // Objective-C expressions + virtual bool visit(ObjCMessageExpressionAST *ast); + QList<Scope *> visibleScopes(const Result &result) const; private: @@ -136,6 +141,16 @@ private: QList<ResolveExpression::Result> _blackList; }; +class CPLUSPLUS_EXPORT ResolveObjCClass +{ +public: + ResolveObjCClass(); + + QList<Symbol *> operator()(Name *name, + const ResolveExpression::Result &p, + const LookupContext &context); +}; + } // end of namespace CPlusPlus |