CppEditor: fix follow symbol under cursor in SIGNAL/SLOT macros

If the cursor was on the first character of a SIGNAL/SLOT name in a
QObject::connect call, the detection in findLinkAt failed.
Token::end() is the first position behind the token, so we must check
if positionInBlock is less than tk.end().
An extra branch has been added to handle the case where the cursor is
on the opening parenthesis after the identifier within a SIGNAL/SLOT
macro. This worked before, because of the "fuzziness" of the former
condition.

Task-number: QTCREATORBUG-10264

Change-Id: I2122bc2c13af1eb6c37dba9134d2b5ab931f80a9
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
Joerg Bornemann
2013-09-27 12:52:54 +02:00
parent ac6a3fd5c7
commit 1ee1416646
2 changed files with 37 additions and 28 deletions

View File

@@ -270,6 +270,23 @@ FollowSymbolUnderCursor::~FollowSymbolUnderCursor()
delete m_virtualFunctionAssistProvider;
}
static int skipMatchingParentheses(const QList<Token> &tokens, int idx, int initialDepth)
{
int j = idx;
int depth = initialDepth;
for (; j < tokens.size(); ++j) {
if (tokens.at(j).is(T_LPAREN)) {
++depth;
} else if (tokens.at(j).is(T_RPAREN)) {
if (!--depth)
break;
}
}
return j;
}
BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &cursor,
bool resolveTarget, const Snapshot &theSnapshot, const Document::Ptr &documentFromSemanticInfo,
SymbolFinder *symbolFinder, bool inNextSplit)
@@ -321,8 +338,8 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
for (int i = 0; i < tokens.size(); ++i) {
const Token &tk = tokens.at(i);
if (((unsigned) positionInBlock) >= tk.begin()
&& ((unsigned) positionInBlock) <= tk.end()) {
if (((unsigned) positionInBlock) >= tk.begin() && ((unsigned) positionInBlock) < tk.end()) {
int closingParenthesisPos = tokens.size();
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))) {
@@ -332,29 +349,25 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
// 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;
}
closingParenthesisPos = skipMatchingParentheses(tokens, i - 1, 0);
}
} else if ((i > 3 && tk.is(T_LPAREN) && tokens.at(i - 1).is(T_IDENTIFIER)
&& tokens.at(i - 2).is(T_LPAREN)
&& (tokens.at(i - 3).is(T_SIGNAL) || tokens.at(i - 3).is(T_SLOT)))) {
// skip until the closing parentheses of the SIGNAL/SLOT macro
closingParenthesisPos = skipMatchingParentheses(tokens, i, 1);
--i; // point to the token before the opening parenthesis
}
if (closingParenthesisPos < 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(closingParenthesisPos).end());
recognizedQtMethod = true;
}
break;
}