diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 793d0312067..92498eef9aa 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -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 &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 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(new TypeOfExpression); typeOfExpression->init(doc, snapshot); // make possible to instantiate templates diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 6fad7736c89..960ea4cec78 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -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()