diff --git a/src/libs/cplusplus/BackwardsScanner.cpp b/src/libs/cplusplus/BackwardsScanner.cpp index 70829a3d077d808c8104dac3a59505f206e153a6..7d1f812a11c94b320c171bd65b9bf3959fb9e990 100644 --- a/src/libs/cplusplus/BackwardsScanner.cpp +++ b/src/libs/cplusplus/BackwardsScanner.cpp @@ -119,7 +119,7 @@ QStringRef BackwardsScanner::textRef(int index) const return _text.midRef(firstToken.begin(), firstToken.length()); } -int BackwardsScanner::previousBlockState(const QTextBlock &block) const +int BackwardsScanner::previousBlockState(const QTextBlock &block) { const QTextBlock prevBlock = block.previous(); diff --git a/src/libs/cplusplus/BackwardsScanner.h b/src/libs/cplusplus/BackwardsScanner.h index 4f82ac28d4cb81674a146ed010f69719faf245da..8ab0685bb12aade01868e15a0f7aa8ef04efbe71 100644 --- a/src/libs/cplusplus/BackwardsScanner.h +++ b/src/libs/cplusplus/BackwardsScanner.h @@ -67,7 +67,7 @@ public: int startOfMatchingBrace(int index) const; int startOfBlock(int index) const; - int previousBlockState(const QTextBlock &block) const; + static int previousBlockState(const QTextBlock &block); int size() const; diff --git a/src/libs/cplusplus/ExpressionUnderCursor.h b/src/libs/cplusplus/ExpressionUnderCursor.h index c8dbbcdf6655aae3a0712acde52b6065a2ca8d1d..e7ef2f9912a462031e7d4ddda76de092796c9d57 100644 --- a/src/libs/cplusplus/ExpressionUnderCursor.h +++ b/src/libs/cplusplus/ExpressionUnderCursor.h @@ -56,7 +56,6 @@ public: private: int startOfExpression(BackwardsScanner &tk, int index); int startOfExpression_helper(BackwardsScanner &tk, int index); - int previousBlockState(const QTextBlock &block); bool isAccessToken(const SimpleToken &tk); private: diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 0dc42ca9cca78a6c28545c284873dba3507d181d..1b19ed4d13b93ebe50d106dfb9b886354d82eae9 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -120,6 +120,25 @@ QList<Scope *> ResolveExpression::visibleScopes(const LookupItem &result) const bool ResolveExpression::visit(BinaryExpressionAST *ast) { + if (tokenKind(ast->binary_op_token) == T_COMMA && ast->right_expression && ast->right_expression->asQtMethod() != 0) { + + if (ast->left_expression && ast->left_expression->asQtMethod() != 0) + thisObject(); + else + accept(ast->left_expression); + + QtMethodAST *qtMethod = ast->right_expression->asQtMethod(); + if (DeclaratorAST *d = qtMethod->declarator) { + if (d->core_declarator) { + if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) + if (NameAST *nameAST = declaratorId->name) + _results = resolveMemberExpression(_results, T_ARROW, nameAST->name); + } + } + + return false; + } + accept(ast->left_expression); return false; } @@ -263,9 +282,15 @@ bool ResolveExpression::visit(BoolLiteralAST *) } bool ResolveExpression::visit(ThisExpressionAST *) +{ + thisObject(); + return false; +} + +void ResolveExpression::thisObject() { if (! _context.symbol()) - return false; + return; Scope *scope = _context.symbol()->scope(); for (; scope; scope = scope->enclosingScope()) { @@ -290,7 +315,6 @@ bool ResolveExpression::visit(ThisExpressionAST *) } } } - return false; } bool ResolveExpression::visit(CompoundExpressionAST *ast) diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 39290ffa24bd97cd1198c02d5018563ff645de7e..eba5b29f91034dcd62ca23411ac9fc5aada9a0b4 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -63,6 +63,7 @@ public: protected: QList<LookupItem> switchResults(const QList<LookupItem> &symbols); + void thisObject(); void addResult(const FullySpecifiedType &ty, Symbol *symbol = 0); void addResult(const LookupItem &result); void addResults(const QList<LookupItem> &results); diff --git a/src/libs/cplusplus/TokenUnderCursor.cpp b/src/libs/cplusplus/TokenUnderCursor.cpp index cf0468cab2f924f340fbd96a0f9325ad974f077b..5cbcdfc7a229d0108357cf97c88c68acc473a456 100644 --- a/src/libs/cplusplus/TokenUnderCursor.cpp +++ b/src/libs/cplusplus/TokenUnderCursor.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "TokenUnderCursor.h" +#include "BackwardsScanner.h" #include <Token.h> #include <QTextCursor> @@ -52,7 +53,7 @@ SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor, QTextBlock * int column = cursor.position() - cursor.block().position(); _text = block.text(); - _tokens = tokenize(_text, previousBlockState(block)); + _tokens = tokenize(_text, BackwardsScanner::previousBlockState(block)); for (int index = _tokens.size() - 1; index != -1; --index) { const SimpleToken &tk = _tokens.at(index); if (tk.position() < column) { @@ -64,15 +65,3 @@ SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor, QTextBlock * return SimpleToken(); } - -int TokenUnderCursor::previousBlockState(const QTextBlock &block) const -{ - const QTextBlock prevBlock = block.previous(); - if (prevBlock.isValid()) { - int state = prevBlock.userState(); - - if (state != -1) - return state; - } - return 0; -} diff --git a/src/libs/cplusplus/TokenUnderCursor.h b/src/libs/cplusplus/TokenUnderCursor.h index 319467d330b7c32bcdcb417ed747cddc18ccafca..af1da311ec132cce7f8757b92c5d8c3ea0e7c5db 100644 --- a/src/libs/cplusplus/TokenUnderCursor.h +++ b/src/libs/cplusplus/TokenUnderCursor.h @@ -52,8 +52,6 @@ public: { return _tokens; } private: - int previousBlockState(const QTextBlock &block) const; - QList<SimpleToken> _tokens; QString _text; }; diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 37772f4b8cae5b4a89fdfdbb5655423a31d5f42b..438da7697c702ed97ae6b686b95ac1a14710f505 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -1347,40 +1347,96 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor, tc.movePosition(QTextCursor::Right); } - static TokenUnderCursor tokenUnderCursor; - - QTextBlock block; - const SimpleToken tk = tokenUnderCursor(tc, &block); - - const int beginOfToken = block.position() + tk.begin(); - const int endOfToken = block.position() + tk.end(); - - // Handle include directives - if (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) { - const unsigned lineno = cursor.blockNumber() + 1; - foreach (const Document::Include &incl, doc->includes()) { - if (incl.line() == lineno && incl.resolved()) { - link.fileName = incl.fileName(); - link.begin = beginOfToken + 1; - link.end = endOfToken - 1; - return link; + + int beginOfToken = 0; + int endOfToken = 0; + + SimpleLexer tokenize; + tokenize.setQtMocRunEnabled(true); + const QString blockText = cursor.block().text(); + const QList<SimpleToken> tokens = tokenize(blockText, BackwardsScanner::previousBlockState(cursor.block())); + + bool recognizedQtMethod = false; + + for (int i = 0; i < tokens.size(); ++i) { + const SimpleToken &tk = tokens.at(i); + + if (column >= tk.begin() && column <= tk.end()) { + if (i >= 2 && tokens.at(i).is(T_IDENTIFIER) && tokens.at(i - 1).is(T_LPAREN) + && (tokens.at(i - 2).is(T_SIGNAL) || tokens.at(i - 2).is(T_SLOT))) { + + // token[i] == T_IDENTIFIER + // token[i + 1] == T_LPAREN + // token[.....] == .... + // token[i + n] == T_RPAREN + + if (i + 1 < tokens.size() && tokens.at(i + 1).is(T_LPAREN)) { + // skip matched parenthesis + int j = i - 1; + int depth = 0; + + for (; j < tokens.size(); ++j) { + if (tokens.at(j).is(T_LPAREN)) + ++depth; + + else if (tokens.at(j).is(T_RPAREN)) { + if (! --depth) + break; + } + } + + if (j < tokens.size()) { + QTextBlock block = cursor.block(); + + beginOfToken = block.position() + tokens.at(i).begin(); + endOfToken = block.position() + tokens.at(i).end(); + + tc.setPosition(block.position() + tokens.at(j).end()); + recognizedQtMethod = true; + } + } } + break; } } - if (tk.isNot(T_IDENTIFIER)) - return link; + if (! recognizedQtMethod) { + static TokenUnderCursor tokenUnderCursor; + + QTextBlock block; + const SimpleToken tk = tokenUnderCursor(tc, &block); + + beginOfToken = block.position() + tk.begin(); + endOfToken = block.position() + tk.end(); + + // Handle include directives + if (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) { + const unsigned lineno = cursor.blockNumber() + 1; + foreach (const Document::Include &incl, doc->includes()) { + if (incl.line() == lineno && incl.resolved()) { + link.fileName = incl.fileName(); + link.begin = beginOfToken + 1; + link.end = endOfToken - 1; + return link; + } + } + } + + if (tk.isNot(T_IDENTIFIER)) + return link; + + tc.setPosition(endOfToken); + } // Find the last symbol up to the cursor position Symbol *lastSymbol = doc->findSymbolAt(line, column); if (!lastSymbol) return link; - tc.setPosition(endOfToken); - // Evaluate the type of the expression under the cursor ExpressionUnderCursor expressionUnderCursor; const QString expression = expressionUnderCursor(tc); + TypeOfExpression typeOfExpression; typeOfExpression.setSnapshot(snapshot); QList<LookupItem> resolvedSymbols =