Commit 251b444c authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppEditor: Fix Follow Symbol on trailing return type

For the function

    auto foo() -> @Foo {}

whereas '@' denotes the cursor position, we detected the expression
under cursor as "foo() -> Foo" and tried to resolve the member "Foo"
within the type of "foo()".

ExpressionUnderCursor can't detect whether we are on a trailing return
type since it only looks at the tokens. Thus, check also the AST.

Task-number: QTCREATORBUG-13096
Change-Id: Ifc14e402fb70e722940e5fa13f1eaaa9973362e4
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@theqtcompany.com>
parent 3ab5e523
......@@ -395,11 +395,11 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s
return symbolFinder->findMatchingDefinition(symbol, snapshot);
}
void maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor)
bool maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor)
{
QTC_ASSERT(expression, return);
QTC_ASSERT(expression, return false);
QTextDocument *textDocument = textCursor.document();
QTC_ASSERT(textDocument, return);
QTC_ASSERT(textDocument, return false);
// Skip white space
QTextCursor cursor(textCursor);
......@@ -407,20 +407,62 @@ void maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &
&& cursor.movePosition(QTextCursor::NextCharacter)) {
}
// Find/Include (...)
// Find/Include "(arg1, arg2, ...)"
if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) {
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true))
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) {
expression->append(cursor.selectedText());
return true;
}
}
return false;
}
bool isCursorOnTrailingReturnType(const QList<AST *> &astPath)
{
for (auto it = astPath.cend() - 1, begin = astPath.cbegin(); it >= begin; --it) {
const auto nextIt = it + 1;
const auto nextNextIt = nextIt + 1;
if (nextNextIt != astPath.cend() && (*it)->asTrailingReturnType()) {
return (*nextIt)->asNamedTypeSpecifier()
&& ((*nextNextIt)->asSimpleName()
|| (*nextNextIt)->asQualifiedName()
|| (*nextNextIt)->asTemplateId());
}
}
return false;
}
void maybeFixExpressionInTrailingReturnType(QString *expression,
const QTextCursor &textCursor,
const Document::Ptr documentFromSemanticInfo)
{
QTC_ASSERT(expression, return);
if (!documentFromSemanticInfo)
return;
const QString arrow = QLatin1String("->");
const int arrowPosition = expression->lastIndexOf(arrow);
if (arrowPosition != -1) {
ASTPath astPathFinder(documentFromSemanticInfo);
const QList<AST *> astPath = astPathFinder(textCursor);
if (isCursorOnTrailingReturnType(astPath))
*expression = expression->mid(arrowPosition + arrow.size()).trimmed();
}
}
QString expressionUnderCursorAsString(const QTextCursor &textCursor,
const Document::Ptr documentFromSemanticInfo,
const LanguageFeatures &features)
{
ExpressionUnderCursor expressionUnderCursor(features);
QString expression = expressionUnderCursor(textCursor);
maybeAppendArgumentOrParameterList(&expression, textCursor);
if (!maybeAppendArgumentOrParameterList(&expression, textCursor))
maybeFixExpressionInTrailingReturnType(&expression, textCursor, documentFromSemanticInfo);
return expression;
}
......@@ -644,7 +686,8 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
// Evaluate the type of the expression under the cursor
QTC_CHECK(document == tc.document());
const QString expression = expressionUnderCursorAsString(tc, features);
const QString expression = expressionUnderCursorAsString(tc, documentFromSemanticInfo,
features);
const QSharedPointer<TypeOfExpression> typeOfExpression(new TypeOfExpression);
typeOfExpression->init(doc, snapshot);
// make possible to instantiate templates
......
......@@ -955,6 +955,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"class Foo { void $" TEST_UNICODE_IDENTIFIER "(); };\n"
"void Foo::@" TEST_UNICODE_IDENTIFIER "() {}\n"
);
QTest::newRow("trailingReturnType") << _(
"struct $Foo {};\n"
"auto foo() -> @Foo {}\n"
);
}
void CppEditorPlugin::test_FollowSymbolUnderCursor()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment