forked from qt-creator/qt-creator
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: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
This commit is contained in:
@@ -395,11 +395,11 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s
|
|||||||
return symbolFinder->findMatchingDefinition(symbol, snapshot);
|
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();
|
QTextDocument *textDocument = textCursor.document();
|
||||||
QTC_ASSERT(textDocument, return);
|
QTC_ASSERT(textDocument, return false);
|
||||||
|
|
||||||
// Skip white space
|
// Skip white space
|
||||||
QTextCursor cursor(textCursor);
|
QTextCursor cursor(textCursor);
|
||||||
@@ -407,20 +407,62 @@ void maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &
|
|||||||
&& cursor.movePosition(QTextCursor::NextCharacter)) {
|
&& cursor.movePosition(QTextCursor::NextCharacter)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find/Include (...)
|
// Find/Include "(arg1, arg2, ...)"
|
||||||
if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) {
|
if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) {
|
||||||
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true))
|
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) {
|
||||||
expression->append(cursor.selectedText());
|
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,
|
QString expressionUnderCursorAsString(const QTextCursor &textCursor,
|
||||||
|
const Document::Ptr documentFromSemanticInfo,
|
||||||
const LanguageFeatures &features)
|
const LanguageFeatures &features)
|
||||||
{
|
{
|
||||||
ExpressionUnderCursor expressionUnderCursor(features);
|
ExpressionUnderCursor expressionUnderCursor(features);
|
||||||
QString expression = expressionUnderCursor(textCursor);
|
QString expression = expressionUnderCursor(textCursor);
|
||||||
|
|
||||||
maybeAppendArgumentOrParameterList(&expression, textCursor);
|
if (!maybeAppendArgumentOrParameterList(&expression, textCursor))
|
||||||
|
maybeFixExpressionInTrailingReturnType(&expression, textCursor, documentFromSemanticInfo);
|
||||||
|
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
@@ -644,7 +686,8 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
|||||||
|
|
||||||
// Evaluate the type of the expression under the cursor
|
// Evaluate the type of the expression under the cursor
|
||||||
QTC_CHECK(document == tc.document());
|
QTC_CHECK(document == tc.document());
|
||||||
const QString expression = expressionUnderCursorAsString(tc, features);
|
const QString expression = expressionUnderCursorAsString(tc, documentFromSemanticInfo,
|
||||||
|
features);
|
||||||
const QSharedPointer<TypeOfExpression> typeOfExpression(new TypeOfExpression);
|
const QSharedPointer<TypeOfExpression> typeOfExpression(new TypeOfExpression);
|
||||||
typeOfExpression->init(doc, snapshot);
|
typeOfExpression->init(doc, snapshot);
|
||||||
// make possible to instantiate templates
|
// make possible to instantiate templates
|
||||||
|
|||||||
@@ -955,6 +955,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
|
|||||||
"class Foo { void $" TEST_UNICODE_IDENTIFIER "(); };\n"
|
"class Foo { void $" TEST_UNICODE_IDENTIFIER "(); };\n"
|
||||||
"void Foo::@" TEST_UNICODE_IDENTIFIER "() {}\n"
|
"void Foo::@" TEST_UNICODE_IDENTIFIER "() {}\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QTest::newRow("trailingReturnType") << _(
|
||||||
|
"struct $Foo {};\n"
|
||||||
|
"auto foo() -> @Foo {}\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppEditorPlugin::test_FollowSymbolUnderCursor()
|
void CppEditorPlugin::test_FollowSymbolUnderCursor()
|
||||||
|
|||||||
Reference in New Issue
Block a user