diff --git a/src/libs/cplusplus/ExpressionUnderCursor.cpp b/src/libs/cplusplus/ExpressionUnderCursor.cpp index 67980ce4e127fbd02232e706283e5832f5925f6c..3bfec589c8caf0d2624614492d6995fcd2684cfb 100644 --- a/src/libs/cplusplus/ExpressionUnderCursor.cpp +++ b/src/libs/cplusplus/ExpressionUnderCursor.cpp @@ -106,8 +106,45 @@ 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; + } else if (tk[index - 2].is(T_LBRACKET)) { + // array subscription: + // array[i + return index - 1; + } else if (tk[index - 2].is(T_COLON)) { + // either of: + // cond ? expr1 : id + // or: + // [receiver messageParam:id + // and in both cases, the id (and only the id) is what we want, so: + return index - 1; + } else if (tk[index - 2].is(T_IDENTIFIER) && tk[index - 3].is(T_LBRACKET)) { + // Very common Objective-C case: + // [receiver message + // which we handle immediately: + return index - 3; + } else { + // See if we are handling an Objective-C messaging expression in the form of: + // [receiver messageParam1:expression messageParam2 + // or: + // [receiver messageParam1:expression messageParam2:expression messageParam3 + // ... etc + int i = index - 1; + while (tk[i].isNot(T_EOF_SYMBOL)) { + if (tk[i].is(T_LBRACKET)) + break; + if (tk[i].is(T_LBRACE) || tk[i].is(T_RBRACE)) + break; + else if (tk[i].is(T_RBRACKET)) + i = tk.startOfMatchingBrace(i + 1) - 1; + else + --i; + } + + int j = i; + while (tk[j].is(T_LBRACKET)) + ++j; + if (tk[j].is(T_IDENTIFIER) && tk[j + 1].is(T_IDENTIFIER)) + return i; } return index - 1; } else if (tk[index - 1].is(T_RPAREN)) { diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 31b5f208b401a3b3a00e587f2d30b2c73434eedb..33ddf1c3e55ebacd237015dec8b63d692d291c5c 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -78,7 +78,7 @@ public: : errorCount(0) { } - virtual void report(int level, + virtual void report(int /*level*/, StringLiteral *fileName, unsigned line, unsigned column, const char *format, va_list ap) @@ -118,6 +118,15 @@ private slots: void expression_under_cursor_1(); + void bracketed_expression_under_cursor_1(); + void bracketed_expression_under_cursor_2(); + void bracketed_expression_under_cursor_3(); + void bracketed_expression_under_cursor_4(); + void bracketed_expression_under_cursor_5(); + void bracketed_expression_under_cursor_6(); + void bracketed_expression_under_cursor_7(); + void bracketed_expression_under_cursor_8(); + void objcClass_1(); }; @@ -447,6 +456,134 @@ void tst_Semantic::expression_under_cursor_1() QCOMPARE(expression, QString("bar")); } +void tst_Semantic::bracketed_expression_under_cursor_1() +{ + const QString plainText = "int i = 0, j[1], k = j[i"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, QString("i")); +} + +void tst_Semantic::bracketed_expression_under_cursor_2() +{ + const QString plainText = "[receiver msg"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, plainText); +} + +void tst_Semantic::bracketed_expression_under_cursor_3() +{ + const QString plainText = "[receiver msgParam1:0 msgParam2"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, plainText); +} + +void tst_Semantic::bracketed_expression_under_cursor_4() +{ + const QString plainText = "[receiver msgParam1:0 msgParam2:@\"zoo\" msgParam3"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, plainText); +} + +void tst_Semantic::bracketed_expression_under_cursor_5() +{ + const QString plainText = "if ([receiver message"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, QString("[receiver message")); +} + +void tst_Semantic::bracketed_expression_under_cursor_6() +{ + const QString plainText = "if ([receiver msgParam1:1 + i[1] msgParam2"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, QString("[receiver msgParam1:1 + i[1] msgParam2")); +} + +void tst_Semantic::bracketed_expression_under_cursor_7() +{ + const QString plainText = "int i = 0, j[1], k = j[(i == 0) ? 0 : i"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, QString("i")); +} + +void tst_Semantic::bracketed_expression_under_cursor_8() +{ + const QString plainText = "[[receiver msg] param1:[receiver msg] param2"; + + QTextDocument textDocument; + textDocument.setPlainText(plainText); + + QTextCursor tc(&textDocument); + tc.movePosition(QTextCursor::End); + + ExpressionUnderCursor expressionUnderCursor; + const QString expression = expressionUnderCursor(tc); + + QCOMPARE(expression, plainText); +} + void tst_Semantic::objcClass_1() { QSharedPointer<Document> doc = document("\n"