forked from qt-creator/qt-creator
CppEditor: refactor FollowSymbol
Create an interface to get the ability to use another FollowSymbol implementation Change-Id: I5802f62523ff3ee47b8a14e487adf43edcb6c9b1 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -23,6 +23,7 @@ SOURCES += \
|
||||
clangeditordocumentprocessor.cpp \
|
||||
clangfixitoperation.cpp \
|
||||
clangfixitoperationsextractor.cpp \
|
||||
clangfollowsymbol.cpp \
|
||||
clangfunctionhintmodel.cpp \
|
||||
clanghighlightingmarksreporter.cpp \
|
||||
clangmodelmanagersupport.cpp \
|
||||
@@ -54,6 +55,7 @@ HEADERS += \
|
||||
clangeditordocumentprocessor.h \
|
||||
clangfixitoperation.h \
|
||||
clangfixitoperationsextractor.h \
|
||||
clangfollowsymbol.h \
|
||||
clangfunctionhintmodel.h \
|
||||
clanghighlightingmarksreporter.h \
|
||||
clangisdiagnosticrelatedtolocation.h \
|
||||
|
@@ -71,6 +71,8 @@ QtcPlugin {
|
||||
"clangfixitoperation.h",
|
||||
"clangfixitoperationsextractor.cpp",
|
||||
"clangfixitoperationsextractor.h",
|
||||
"clangfollowsymbol.cpp",
|
||||
"clangfollowsymbol.h",
|
||||
"clangfunctionhintmodel.cpp",
|
||||
"clangfunctionhintmodel.h",
|
||||
"clanghighlightingmarksreporter.cpp",
|
||||
|
83
src/plugins/clangcodemodel/clangfollowsymbol.cpp
Normal file
83
src/plugins/clangcodemodel/clangfollowsymbol.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "clangfollowsymbol.h"
|
||||
#include "clangeditordocumentprocessor.h"
|
||||
#include "texteditor/texteditor.h"
|
||||
#include "texteditor/convenience.h"
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
|
||||
const CppTools::CursorInEditor &data,
|
||||
bool resolveTarget,
|
||||
const CPlusPlus::Snapshot &,
|
||||
const CPlusPlus::Document::Ptr &,
|
||||
CppTools::SymbolFinder *,
|
||||
bool)
|
||||
{
|
||||
Link link;
|
||||
|
||||
int lineNumber = 0, positionInBlock = 0;
|
||||
QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor());
|
||||
TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber,
|
||||
&positionInBlock);
|
||||
const unsigned line = lineNumber;
|
||||
const unsigned column = positionInBlock + 1;
|
||||
|
||||
if (!resolveTarget)
|
||||
return link;
|
||||
ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
|
||||
data.filePath().toString());
|
||||
if (!processor)
|
||||
return link;
|
||||
|
||||
QFuture<CppTools::SymbolInfo> info
|
||||
= processor->requestFollowSymbol(static_cast<int>(line),
|
||||
static_cast<int>(column),
|
||||
resolveTarget);
|
||||
if (info.isCanceled())
|
||||
return link;
|
||||
|
||||
while (!info.isFinished()) {
|
||||
if (info.isCanceled())
|
||||
return link;
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
}
|
||||
CppTools::SymbolInfo result = info.result();
|
||||
|
||||
if (result.failedToFollow)
|
||||
return link;
|
||||
|
||||
// We did not fail but the result is empty
|
||||
if (result.fileName.isEmpty())
|
||||
return link;
|
||||
|
||||
return Link(result.fileName, result.startLine, result.startColumn - 1);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangCodeModel
|
45
src/plugins/clangcodemodel/clangfollowsymbol.h
Normal file
45
src/plugins/clangcodemodel/clangfollowsymbol.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cpptools/followsymbolinterface.h>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class ClangFollowSymbol : public CppTools::FollowSymbolInterface
|
||||
{
|
||||
public:
|
||||
Link findLink(const CppTools::CursorInEditor &data,
|
||||
bool resolveTarget,
|
||||
const CPlusPlus::Snapshot &,
|
||||
const CPlusPlus::Document::Ptr &,
|
||||
CppTools::SymbolFinder *,
|
||||
bool) override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangCodeModel
|
@@ -28,6 +28,7 @@
|
||||
#include "clangconstants.h"
|
||||
#include "clangeditordocumentprocessor.h"
|
||||
#include "clangutils.h"
|
||||
#include "clangfollowsymbol.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
@@ -52,6 +53,12 @@ using namespace ClangCodeModel::Internal;
|
||||
|
||||
static ModelManagerSupportClang *m_instance = 0;
|
||||
|
||||
static bool useClangFollowSymbol()
|
||||
{
|
||||
static bool use = qEnvironmentVariableIntValue("QTC_CLANG_FOLLOW_SYMBOL");
|
||||
return use;
|
||||
}
|
||||
|
||||
static CppTools::CppModelManager *cppModelManager()
|
||||
{
|
||||
return CppTools::CppModelManager::instance();
|
||||
@@ -63,6 +70,9 @@ ModelManagerSupportClang::ModelManagerSupportClang()
|
||||
QTC_CHECK(!m_instance);
|
||||
m_instance = this;
|
||||
|
||||
if (useClangFollowSymbol())
|
||||
m_followSymbol.reset(new ClangFollowSymbol);
|
||||
|
||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||
connect(editorManager, &Core::EditorManager::editorOpened,
|
||||
this, &ModelManagerSupportClang::onEditorOpened);
|
||||
@@ -96,6 +106,11 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis
|
||||
return &m_completionAssistProvider;
|
||||
}
|
||||
|
||||
CppTools::FollowSymbolInterface *ModelManagerSupportClang::followSymbolInterface()
|
||||
{
|
||||
return m_followSymbol.get();
|
||||
}
|
||||
|
||||
CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor(
|
||||
TextEditor::TextDocument *baseTextDocument)
|
||||
{
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QMenu;
|
||||
class QWidget;
|
||||
@@ -44,6 +46,8 @@ namespace TextEditor { class TextEditorWidget; }
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class ClangFollowSymbol;
|
||||
|
||||
class ModelManagerSupportClang:
|
||||
public QObject,
|
||||
public CppTools::ModelManagerSupport
|
||||
@@ -57,6 +61,7 @@ public:
|
||||
CppTools::CppCompletionAssistProvider *completionAssistProvider() override;
|
||||
CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(
|
||||
TextEditor::TextDocument *baseTextDocument) override;
|
||||
CppTools::FollowSymbolInterface *followSymbolInterface() override;
|
||||
|
||||
IpcCommunicator &ipcCommunicator();
|
||||
QString dummyUiHeaderOnDiskDirPath() const;
|
||||
@@ -100,6 +105,7 @@ private:
|
||||
UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
|
||||
IpcCommunicator m_ipcCommunicator;
|
||||
ClangCompletionAssistProvider m_completionAssistProvider;
|
||||
std::unique_ptr<ClangFollowSymbol> m_followSymbol;
|
||||
};
|
||||
|
||||
class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider
|
||||
|
@@ -386,12 +386,6 @@ CppEditorDocument::cursorInfo(const CppTools::CursorInfoParams ¶ms)
|
||||
return processor()->cursorInfo(params);
|
||||
}
|
||||
|
||||
QFuture<CppTools::SymbolInfo>
|
||||
CppEditorDocument::requestFollowSymbol(int line, int column, bool resolveTarget)
|
||||
{
|
||||
return processor()->requestFollowSymbol(line, column, resolveTarget);
|
||||
}
|
||||
|
||||
const MinimizableInfoBars &CppEditorDocument::minimizableInfoBars() const
|
||||
{
|
||||
return m_minimizableInfoBars;
|
||||
|
@@ -67,9 +67,6 @@ public:
|
||||
ParseContextModel &parseContextModel();
|
||||
|
||||
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams ¶ms);
|
||||
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line,
|
||||
int column,
|
||||
bool resolveTarget = true);
|
||||
|
||||
signals:
|
||||
void codeWarningsUpdated(unsigned contentsRevision,
|
||||
|
@@ -93,6 +93,9 @@ private slots:
|
||||
void test_FollowSymbolUnderCursor_data();
|
||||
void test_FollowSymbolUnderCursor();
|
||||
|
||||
void test_FollowSymbolUnderCursor_QTCREATORBUG7903_data();
|
||||
void test_FollowSymbolUnderCursor_QTCREATORBUG7903();
|
||||
|
||||
void test_FollowSymbolUnderCursor_followCall_data();
|
||||
void test_FollowSymbolUnderCursor_followCall();
|
||||
|
||||
|
@@ -129,8 +129,8 @@ public:
|
||||
|
||||
CppLocalRenaming m_localRenaming;
|
||||
CppUseSelectionsUpdater m_useSelectionsUpdater;
|
||||
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
|
||||
CppSelectionChanger m_cppSelectionChanger;
|
||||
FollowSymbolUnderCursor m_builtinFollowSymbol;
|
||||
CppRefactoringEngine m_builtinRefactoringEngine;
|
||||
};
|
||||
|
||||
@@ -141,7 +141,6 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
|
||||
, m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q))
|
||||
, m_localRenaming(q)
|
||||
, m_useSelectionsUpdater(q)
|
||||
, m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q))
|
||||
, m_cppSelectionChanger()
|
||||
{}
|
||||
|
||||
@@ -647,12 +646,23 @@ CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor,
|
||||
if (!d->m_modelManager)
|
||||
return Link();
|
||||
|
||||
return d->m_followSymbolUnderCursor->findLink(cursor,
|
||||
resolveTarget,
|
||||
d->m_modelManager->snapshot(),
|
||||
d->m_lastSemanticInfo.doc,
|
||||
d->m_modelManager->symbolFinder(),
|
||||
inNextSplit);
|
||||
const Utils::FileName &filePath = textDocument()->filePath();
|
||||
if (!resolveTarget) {
|
||||
// TODO: get that part also from clang
|
||||
return d->m_builtinFollowSymbol.findLink(CppTools::CursorInEditor{cursor, filePath, this},
|
||||
resolveTarget,
|
||||
d->m_modelManager->snapshot(),
|
||||
d->m_lastSemanticInfo.doc,
|
||||
d->m_modelManager->symbolFinder(),
|
||||
inNextSplit);
|
||||
}
|
||||
|
||||
return followSymbolInterface()->findLink(CppTools::CursorInEditor{cursor, filePath, this},
|
||||
resolveTarget,
|
||||
d->m_modelManager->snapshot(),
|
||||
d->m_lastSemanticInfo.doc,
|
||||
d->m_modelManager->symbolFinder(),
|
||||
inNextSplit);
|
||||
}
|
||||
|
||||
unsigned CppEditorWidget::documentRevision() const
|
||||
@@ -687,6 +697,14 @@ RefactoringEngineInterface *CppEditorWidget::refactoringEngine() const
|
||||
: static_cast<RefactoringEngineInterface *>(&d->m_builtinRefactoringEngine);
|
||||
}
|
||||
|
||||
CppTools::FollowSymbolInterface *CppEditorWidget::followSymbolInterface() const
|
||||
{
|
||||
CppTools::FollowSymbolInterface *followSymbol
|
||||
= CppTools::CppModelManager::instance()->followSymbolInterface();
|
||||
return followSymbol ? followSymbol
|
||||
: static_cast<CppTools::FollowSymbolInterface *>(&d->m_builtinFollowSymbol);
|
||||
}
|
||||
|
||||
bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const
|
||||
{
|
||||
return d->m_lastSemanticInfo.doc && d->m_lastSemanticInfo.revision == documentRevision()
|
||||
@@ -973,11 +991,6 @@ void CppEditorWidget::applyDeclDefLinkChanges(bool jumpToMatch)
|
||||
updateFunctionDeclDefLink();
|
||||
}
|
||||
|
||||
FollowSymbolUnderCursor *CppEditorWidget::followSymbolUnderCursorDelegate()
|
||||
{
|
||||
return d->m_followSymbolUnderCursor.data();
|
||||
}
|
||||
|
||||
void CppEditorWidget::encourageApply()
|
||||
{
|
||||
if (d->m_localRenaming.encourageApply())
|
||||
|
@@ -32,6 +32,7 @@
|
||||
namespace CppTools {
|
||||
class CppEditorOutline;
|
||||
class RefactoringEngineInterface;
|
||||
class FollowSymbolInterface;
|
||||
class SemanticInfo;
|
||||
class ProjectPart;
|
||||
}
|
||||
@@ -42,7 +43,6 @@ namespace Internal {
|
||||
class CppEditorDocument;
|
||||
|
||||
class CppEditorWidgetPrivate;
|
||||
class FollowSymbolUnderCursor;
|
||||
class FunctionDeclDefLink;
|
||||
|
||||
class CppEditorWidget : public TextEditor::TextEditorWidget
|
||||
@@ -67,8 +67,6 @@ public:
|
||||
TextEditor::AssistKind kind,
|
||||
TextEditor::AssistReason reason) const override;
|
||||
|
||||
FollowSymbolUnderCursor *followSymbolUnderCursorDelegate(); // exposed for tests
|
||||
|
||||
void encourageApply() override;
|
||||
|
||||
void paste() override;
|
||||
@@ -89,6 +87,8 @@ public:
|
||||
static bool isWidgetHighlighted(QWidget *widget);
|
||||
|
||||
void updateSemanticInfo();
|
||||
|
||||
CppTools::FollowSymbolInterface *followSymbolInterface() const;
|
||||
protected:
|
||||
bool event(QEvent *e) override;
|
||||
void contextMenuEvent(QContextMenuEvent *) override;
|
||||
|
@@ -55,12 +55,6 @@ typedef TextEditorWidget::Link Link;
|
||||
|
||||
namespace {
|
||||
|
||||
static bool useClangFollowSymbol()
|
||||
{
|
||||
static bool use = qEnvironmentVariableIntValue("QTC_CLANG_FOLLOW_SYMBOL");
|
||||
return use;
|
||||
}
|
||||
|
||||
class VirtualFunctionHelper {
|
||||
public:
|
||||
VirtualFunctionHelper(TypeOfExpression &typeOfExpression,
|
||||
@@ -305,9 +299,9 @@ inline LookupItem skipForwardDeclarations(const QList<LookupItem> &resolvedSymbo
|
||||
return result;
|
||||
}
|
||||
|
||||
CppEditorWidget::Link attemptFuncDeclDef(const QTextCursor &cursor,
|
||||
CppEditorWidget *, Snapshot snapshot, const Document::Ptr &document,
|
||||
SymbolFinder *symbolFinder)
|
||||
CppEditorWidget::Link attemptFuncDeclDef(const QTextCursor &cursor, Snapshot snapshot,
|
||||
const Document::Ptr &document,
|
||||
SymbolFinder *symbolFinder)
|
||||
{
|
||||
Link result;
|
||||
QTC_ASSERT(document, return result);
|
||||
@@ -467,17 +461,11 @@ QString expressionUnderCursorAsString(const QTextCursor &textCursor,
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
FollowSymbolUnderCursor::FollowSymbolUnderCursor(CppEditorWidget *widget)
|
||||
: m_widget(widget)
|
||||
, m_virtualFunctionAssistProvider(new VirtualFunctionAssistProvider)
|
||||
FollowSymbolUnderCursor::FollowSymbolUnderCursor()
|
||||
: m_virtualFunctionAssistProvider(new VirtualFunctionAssistProvider)
|
||||
{
|
||||
}
|
||||
|
||||
FollowSymbolUnderCursor::~FollowSymbolUnderCursor()
|
||||
{
|
||||
delete m_virtualFunctionAssistProvider;
|
||||
}
|
||||
|
||||
static int skipMatchingParentheses(const Tokens &tokens, int idx, int initialDepth)
|
||||
{
|
||||
int j = idx;
|
||||
@@ -495,61 +483,28 @@ static int skipMatchingParentheses(const Tokens &tokens, int idx, int initialDep
|
||||
return j;
|
||||
}
|
||||
|
||||
bool FollowSymbolUnderCursor::processorFollowSymbol(uint line, uint column, bool resolveTarget,
|
||||
Link &linkResult)
|
||||
{
|
||||
if (!useClangFollowSymbol())
|
||||
return false;
|
||||
CppEditorDocument* editorDocument = m_widget->cppEditorDocument();
|
||||
if (!editorDocument)
|
||||
return false;
|
||||
|
||||
QFuture<CppTools::SymbolInfo> info
|
||||
= editorDocument->requestFollowSymbol(static_cast<int>(line),
|
||||
static_cast<int>(column),
|
||||
resolveTarget);
|
||||
if (info.isCanceled())
|
||||
return false;
|
||||
|
||||
while (!info.isFinished()) {
|
||||
if (info.isCanceled())
|
||||
return false;
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
}
|
||||
CppTools::SymbolInfo result = info.result();
|
||||
|
||||
// Try again with built-in code model (happens with some includes)
|
||||
if (result.failedToFollow)
|
||||
return false;
|
||||
|
||||
// We did not fail but the result is empty
|
||||
if (result.fileName.isEmpty())
|
||||
return true;
|
||||
|
||||
linkResult = Link(result.fileName, result.startLine, result.startColumn - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &cursor,
|
||||
bool resolveTarget, const Snapshot &theSnapshot, const Document::Ptr &documentFromSemanticInfo,
|
||||
SymbolFinder *symbolFinder, bool inNextSplit)
|
||||
Link FollowSymbolUnderCursor::findLink(
|
||||
const CppTools::CursorInEditor &data,
|
||||
bool resolveTarget,
|
||||
const Snapshot &theSnapshot,
|
||||
const Document::Ptr &documentFromSemanticInfo,
|
||||
SymbolFinder *symbolFinder,
|
||||
bool inNextSplit)
|
||||
{
|
||||
Link link;
|
||||
|
||||
int lineNumber = 0, positionInBlock = 0;
|
||||
m_widget->convertPosition(cursor.position(), &lineNumber, &positionInBlock);
|
||||
QTextCursor cursor = data.cursor();
|
||||
QTextDocument *document = cursor.document();
|
||||
TextEditor::Convenience::convertPosition(document, cursor.position(), &lineNumber,
|
||||
&positionInBlock);
|
||||
const unsigned line = lineNumber;
|
||||
const unsigned column = positionInBlock + 1;
|
||||
|
||||
if (resolveTarget && processorFollowSymbol(line, column, resolveTarget, link))
|
||||
return link;
|
||||
|
||||
Snapshot snapshot = theSnapshot;
|
||||
|
||||
// Move to end of identifier
|
||||
QTextCursor tc = cursor;
|
||||
QTextDocument *document = m_widget->document();
|
||||
QChar ch = document->characterAt(tc.position());
|
||||
while (CppTools::isValidIdentifierChar(ch)) {
|
||||
tc.movePosition(QTextCursor::NextCharacter);
|
||||
@@ -564,7 +519,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
while (document->characterAt(pos).isSpace())
|
||||
++pos;
|
||||
if (document->characterAt(pos) == QLatin1Char('(')) {
|
||||
link = attemptFuncDeclDef(cursor, m_widget, snapshot, documentFromSemanticInfo,
|
||||
link = attemptFuncDeclDef(cursor, snapshot, documentFromSemanticInfo,
|
||||
symbolFinder);
|
||||
if (link.hasValidLinkText())
|
||||
return link;
|
||||
@@ -636,7 +591,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
&& unsigned(positionInBlock) <= tk.utf16charsEnd()) {
|
||||
cursorRegionReached = true;
|
||||
if (tk.is(T_OPERATOR)) {
|
||||
link = attemptFuncDeclDef(cursor, m_widget, theSnapshot,
|
||||
link = attemptFuncDeclDef(cursor, theSnapshot,
|
||||
documentFromSemanticInfo, symbolFinder);
|
||||
if (link.hasValidLinkText())
|
||||
return link;
|
||||
@@ -644,7 +599,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
QTextCursor c = cursor;
|
||||
c.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor,
|
||||
positionInBlock - tokens.at(i - 1).utf16charsBegin());
|
||||
link = attemptFuncDeclDef(c, m_widget, theSnapshot, documentFromSemanticInfo,
|
||||
link = attemptFuncDeclDef(c, theSnapshot, documentFromSemanticInfo,
|
||||
symbolFinder);
|
||||
if (link.hasValidLinkText())
|
||||
return link;
|
||||
@@ -655,8 +610,11 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
}
|
||||
}
|
||||
|
||||
CppEditorWidget *editorWidget = static_cast<CppEditorWidget *>(data.editorWidget());
|
||||
if (!editorWidget)
|
||||
return link;
|
||||
// Now we prefer the doc from the snapshot with macros expanded.
|
||||
Document::Ptr doc = snapshot.document(m_widget->textDocument()->filePath());
|
||||
Document::Ptr doc = snapshot.document(editorWidget->textDocument()->filePath());
|
||||
if (!doc) {
|
||||
doc = documentFromSemanticInfo;
|
||||
if (!doc)
|
||||
@@ -705,7 +663,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
} else if (const Document::MacroUse *use = doc->findMacroUseAt(endOfToken - 1)) {
|
||||
const QString fileName = use->macro().fileName();
|
||||
if (fileName == CppModelManager::editorConfigurationFileName()) {
|
||||
m_widget->showPreProcessorWidget();
|
||||
editorWidget->showPreProcessorWidget();
|
||||
} else if (fileName != CppModelManager::configurationFileName()) {
|
||||
const Macro ¯o = use->macro();
|
||||
link.targetFileName = macro.fileName();
|
||||
@@ -739,7 +697,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
if (Symbol *d = r.declaration()) {
|
||||
if (d->isDeclaration() || d->isFunction()) {
|
||||
const QString fileName = QString::fromUtf8(d->fileName(), d->fileNameLength());
|
||||
if (m_widget->textDocument()->filePath().toString() == fileName) {
|
||||
if (editorWidget->textDocument()->filePath().toString() == fileName) {
|
||||
if (unsigned(lineNumber) == d->line()
|
||||
&& unsigned(positionInBlock) >= d->column()) { // TODO: check the end
|
||||
result = r; // take the symbol under cursor.
|
||||
@@ -748,7 +706,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
}
|
||||
} else if (d->isUsingDeclaration()) {
|
||||
int tokenBeginLineNumber = 0, tokenBeginColumnNumber = 0;
|
||||
m_widget->convertPosition(beginOfToken, &tokenBeginLineNumber,
|
||||
editorWidget->convertPosition(beginOfToken, &tokenBeginLineNumber,
|
||||
&tokenBeginColumnNumber);
|
||||
if (unsigned(tokenBeginLineNumber) > d->line()
|
||||
|| (unsigned(tokenBeginLineNumber) == d->line()
|
||||
@@ -778,7 +736,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
params.openInNextSplit = inNextSplit;
|
||||
|
||||
if (m_virtualFunctionAssistProvider->configure(params)) {
|
||||
m_widget->invokeAssist(FollowSymbol, m_virtualFunctionAssistProvider);
|
||||
editorWidget->invokeAssist(FollowSymbol, m_virtualFunctionAssistProvider.data());
|
||||
m_virtualFunctionAssistProvider->clearParams();
|
||||
}
|
||||
|
||||
@@ -827,12 +785,13 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
|
||||
return Link();
|
||||
}
|
||||
|
||||
VirtualFunctionAssistProvider *FollowSymbolUnderCursor::virtualFunctionAssistProvider()
|
||||
QSharedPointer<VirtualFunctionAssistProvider> FollowSymbolUnderCursor::virtualFunctionAssistProvider()
|
||||
{
|
||||
return m_virtualFunctionAssistProvider;
|
||||
}
|
||||
|
||||
void FollowSymbolUnderCursor::setVirtualFunctionAssistProvider(VirtualFunctionAssistProvider *provider)
|
||||
void FollowSymbolUnderCursor::setVirtualFunctionAssistProvider(
|
||||
const QSharedPointer<VirtualFunctionAssistProvider> &provider)
|
||||
{
|
||||
m_virtualFunctionAssistProvider = provider;
|
||||
}
|
||||
|
@@ -25,44 +25,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cplusplus/CppDocument.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTextCursor;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace CppTools { class SymbolFinder; }
|
||||
#include <cpptools/followsymbolinterface.h>
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
class CppEditorWidget;
|
||||
class VirtualFunctionAssistProvider;
|
||||
|
||||
class FollowSymbolUnderCursor
|
||||
class FollowSymbolUnderCursor : public CppTools::FollowSymbolInterface
|
||||
{
|
||||
public:
|
||||
typedef TextEditor::TextEditorWidget::Link Link;
|
||||
FollowSymbolUnderCursor();
|
||||
|
||||
FollowSymbolUnderCursor(CppEditorWidget *widget);
|
||||
~FollowSymbolUnderCursor();
|
||||
|
||||
Link findLink(const QTextCursor &cursor, bool resolveTarget,
|
||||
Link findLink(const CppTools::CursorInEditor &data,
|
||||
bool resolveTarget,
|
||||
const CPlusPlus::Snapshot &snapshot,
|
||||
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
|
||||
CppTools::SymbolFinder *symbolFinder, bool inNextSplit);
|
||||
CppTools::SymbolFinder *symbolFinder,
|
||||
bool inNextSplit) override;
|
||||
|
||||
VirtualFunctionAssistProvider *virtualFunctionAssistProvider();
|
||||
void setVirtualFunctionAssistProvider(VirtualFunctionAssistProvider *provider);
|
||||
QSharedPointer<VirtualFunctionAssistProvider> virtualFunctionAssistProvider();
|
||||
void setVirtualFunctionAssistProvider(
|
||||
const QSharedPointer<VirtualFunctionAssistProvider> &provider);
|
||||
|
||||
private:
|
||||
// Try to follow symbol with clang processor
|
||||
// Returns false if it has failed and we want to try again with built-in one
|
||||
bool processorFollowSymbol(uint line, uint column, bool resolveTarget,
|
||||
Link &result);
|
||||
CppEditorWidget *m_widget;
|
||||
VirtualFunctionAssistProvider *m_virtualFunctionAssistProvider;
|
||||
QSharedPointer<VirtualFunctionAssistProvider> m_virtualFunctionAssistProvider;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "cppvirtualfunctionproposalitem.h"
|
||||
|
||||
#include <cpptools/cpptoolstestcase.h>
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
|
||||
#include <texteditor/codeassist/genericproposalmodel.h>
|
||||
#include <texteditor/codeassist/iassistprocessor.h>
|
||||
@@ -326,19 +327,37 @@ F2TestCase::F2TestCase(CppEditorAction action,
|
||||
switch (action) {
|
||||
case FollowSymbolUnderCursorAction: {
|
||||
CppEditorWidget *widget = initialTestFile->m_editorWidget;
|
||||
FollowSymbolUnderCursor *delegate = widget->followSymbolUnderCursorDelegate();
|
||||
VirtualFunctionAssistProvider *original = delegate->virtualFunctionAssistProvider();
|
||||
FollowSymbolInterface* delegate = widget->followSymbolInterface();
|
||||
if (!delegate)
|
||||
QFAIL("No follow symbol interface");
|
||||
auto* builtinFollowSymbol = dynamic_cast<FollowSymbolUnderCursor *>(delegate);
|
||||
if (!builtinFollowSymbol) {
|
||||
if (filePaths.size() > 1)
|
||||
QSKIP("Clang FollowSymbol does not currently support multiple files (except cpp+header)");
|
||||
const QString curTestName = QLatin1String(QTest::currentTestFunction());
|
||||
if (curTestName == "test_FollowSymbolUnderCursor_QObject_connect"
|
||||
|| curTestName == "test_FollowSymbolUnderCursor_virtualFunctionCall"
|
||||
|| curTestName == "test_FollowSymbolUnderCursor_QTCREATORBUG7903") {
|
||||
QSKIP((curTestName + " is not supported by Clang FollowSymbol").toLatin1());
|
||||
}
|
||||
|
||||
initialTestFile->m_editorWidget->openLinkUnderCursor();
|
||||
break;
|
||||
}
|
||||
|
||||
QSharedPointer<VirtualFunctionAssistProvider> original
|
||||
= builtinFollowSymbol->virtualFunctionAssistProvider();
|
||||
|
||||
// Set test provider, run and get results
|
||||
QScopedPointer<VirtualFunctionTestAssistProvider> testProvider(
|
||||
QSharedPointer<VirtualFunctionTestAssistProvider> testProvider(
|
||||
new VirtualFunctionTestAssistProvider(widget));
|
||||
delegate->setVirtualFunctionAssistProvider(testProvider.data());
|
||||
builtinFollowSymbol->setVirtualFunctionAssistProvider(testProvider);
|
||||
initialTestFile->m_editorWidget->openLinkUnderCursor();
|
||||
immediateVirtualSymbolResults = testProvider->m_immediateItems;
|
||||
finalVirtualSymbolResults = testProvider->m_finalItems;
|
||||
|
||||
// Restore original test provider
|
||||
delegate->setVirtualFunctionAssistProvider(original);
|
||||
builtinFollowSymbol->setVirtualFunctionAssistProvider(original);
|
||||
break;
|
||||
}
|
||||
case SwitchBetweenMethodDeclarationDefinitionAction:
|
||||
@@ -870,41 +889,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
|
||||
"@Container<int> container;\n"
|
||||
);
|
||||
|
||||
QTest::newRow("using_QTCREATORBUG7903_globalNamespace") << _(
|
||||
"namespace NS {\n"
|
||||
"class Foo {};\n"
|
||||
"}\n"
|
||||
"using NS::$Foo;\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" @Foo foo;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("using_QTCREATORBUG7903_namespace") << _(
|
||||
"namespace NS {\n"
|
||||
"class Foo {};\n"
|
||||
"}\n"
|
||||
"namespace NS1 {\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" using NS::$Foo;\n"
|
||||
" @Foo foo;\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("using_QTCREATORBUG7903_insideFunction") << _(
|
||||
"namespace NS {\n"
|
||||
"class Foo {};\n"
|
||||
"}\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" using NS::$Foo;\n"
|
||||
" @Foo foo;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("matchFunctionSignature_Follow_1") << _(
|
||||
"class Foo {\n"
|
||||
" void @foo(int);\n"
|
||||
@@ -993,6 +977,8 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
|
||||
);
|
||||
|
||||
QTest::newRow("template_alias") << _(
|
||||
"template<class T>"
|
||||
"class Bar;"
|
||||
"template<class $T>\n"
|
||||
"using Foo = Bar<@T>;\n"
|
||||
);
|
||||
@@ -1004,6 +990,51 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor()
|
||||
F2TestCase(F2TestCase::FollowSymbolUnderCursorAction, singleDocument(source));
|
||||
}
|
||||
|
||||
void CppEditorPlugin::test_FollowSymbolUnderCursor_QTCREATORBUG7903_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("source");
|
||||
QTest::newRow("using_QTCREATORBUG7903_globalNamespace") << _(
|
||||
"namespace NS {\n"
|
||||
"class Foo {};\n"
|
||||
"}\n"
|
||||
"using NS::$Foo;\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" @Foo foo;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("using_QTCREATORBUG7903_namespace") << _(
|
||||
"namespace NS {\n"
|
||||
"class Foo {};\n"
|
||||
"}\n"
|
||||
"namespace NS1 {\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" using NS::$Foo;\n"
|
||||
" @Foo foo;\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("using_QTCREATORBUG7903_insideFunction") << _(
|
||||
"namespace NS {\n"
|
||||
"class Foo {};\n"
|
||||
"}\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" using NS::$Foo;\n"
|
||||
" @Foo foo;\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
void CppEditorPlugin::test_FollowSymbolUnderCursor_QTCREATORBUG7903()
|
||||
{
|
||||
QFETCH(QByteArray, source);
|
||||
F2TestCase(F2TestCase::FollowSymbolUnderCursorAction, singleDocument(source));
|
||||
}
|
||||
|
||||
void CppEditorPlugin::test_FollowSymbolUnderCursor_followCall_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("variableDeclaration"); // without semicolon, can be ""
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include "cpptoolsreuse.h"
|
||||
#include "editordocumenthandle.h"
|
||||
#include "symbolfinder.h"
|
||||
#include "followsymbolinterface.h"
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -274,6 +275,11 @@ RefactoringEngineInterface *CppModelManager::refactoringEngine()
|
||||
return instance()->d->m_refactoringEngine;
|
||||
}
|
||||
|
||||
FollowSymbolInterface *CppModelManager::followSymbolInterface() const
|
||||
{
|
||||
return d->m_activeModelManagerSupport->followSymbolInterface();
|
||||
}
|
||||
|
||||
QString CppModelManager::configurationFileName()
|
||||
{
|
||||
return Preprocessor::configurationFileName();
|
||||
|
@@ -54,6 +54,7 @@ class CppEditorDocumentHandle;
|
||||
class CppIndexingSupport;
|
||||
class ModelManagerSupportProvider;
|
||||
class RefactoringEngineInterface;
|
||||
class FollowSymbolInterface;
|
||||
class SymbolFinder;
|
||||
class WorkingCopy;
|
||||
|
||||
@@ -152,6 +153,7 @@ public:
|
||||
CppCompletionAssistProvider *completionAssistProvider() const;
|
||||
BaseEditorDocumentProcessor *editorDocumentProcessor(
|
||||
TextEditor::TextDocument *baseTextDocument) const;
|
||||
FollowSymbolInterface *followSymbolInterface() const;
|
||||
|
||||
void setIndexingSupport(CppIndexingSupport *indexingSupport);
|
||||
CppIndexingSupport *indexingSupport();
|
||||
|
@@ -36,6 +36,7 @@ namespace CppTools {
|
||||
|
||||
class BaseEditorDocumentProcessor;
|
||||
class CppCompletionAssistProvider;
|
||||
class FollowSymbolInterface;
|
||||
|
||||
class CPPTOOLS_EXPORT ModelManagerSupport
|
||||
{
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
|
||||
virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
|
||||
TextEditor::TextDocument *baseTextDocument) = 0;
|
||||
virtual FollowSymbolInterface *followSymbolInterface() = 0;
|
||||
};
|
||||
|
||||
class CPPTOOLS_EXPORT ModelManagerSupportProvider
|
||||
|
@@ -69,3 +69,8 @@ CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvid
|
||||
{
|
||||
return m_completionAssistProvider.data();
|
||||
}
|
||||
|
||||
FollowSymbolInterface *ModelManagerSupportInternal::followSymbolInterface()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ public:
|
||||
virtual CppCompletionAssistProvider *completionAssistProvider();
|
||||
virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
|
||||
TextEditor::TextDocument *baseTextDocument);
|
||||
FollowSymbolInterface *followSymbolInterface() override;
|
||||
|
||||
private:
|
||||
QScopedPointer<CppCompletionAssistProvider> m_completionAssistProvider;
|
||||
|
@@ -63,6 +63,7 @@ HEADERS += \
|
||||
cppworkingcopy.h \
|
||||
doxygengenerator.h \
|
||||
editordocumenthandle.h \
|
||||
followsymbolinterface.h \
|
||||
functionutils.h \
|
||||
generatedcodemodelsupport.h \
|
||||
includeutils.h \
|
||||
|
@@ -164,6 +164,7 @@ Project {
|
||||
"doxygengenerator.h",
|
||||
"editordocumenthandle.cpp",
|
||||
"editordocumenthandle.h",
|
||||
"followsymbolinterface.h",
|
||||
"functionutils.cpp",
|
||||
"functionutils.h",
|
||||
"generatedcodemodelsupport.cpp",
|
||||
|
53
src/plugins/cpptools/followsymbolinterface.h
Normal file
53
src/plugins/cpptools/followsymbolinterface.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpptools_global.h"
|
||||
#include "cursorineditor.h"
|
||||
|
||||
#include <cplusplus/CppDocument.h>
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
namespace CppTools {
|
||||
|
||||
class SymbolFinder;
|
||||
|
||||
class CPPTOOLS_EXPORT FollowSymbolInterface
|
||||
{
|
||||
public:
|
||||
using Link = TextEditor::TextEditorWidget::Link;
|
||||
|
||||
virtual ~FollowSymbolInterface() {}
|
||||
virtual Link findLink(const CursorInEditor &data,
|
||||
bool resolveTarget,
|
||||
const CPlusPlus::Snapshot &snapshot,
|
||||
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
|
||||
SymbolFinder *symbolFinder,
|
||||
bool inNextSplit) = 0;
|
||||
};
|
||||
|
||||
} // namespace CppTools
|
@@ -95,6 +95,13 @@ static bool isValidIdentifierChar(const QChar &c)
|
||||
|| c.isLowSurrogate();
|
||||
}
|
||||
|
||||
static bool isAfterOperatorKeyword(QTextCursor cursor)
|
||||
{
|
||||
cursor.movePosition(QTextCursor::PreviousWord);
|
||||
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||
return cursor.selectedText() == "operator";
|
||||
}
|
||||
|
||||
QTextCursor wordStartCursor(const QTextCursor &textCursor)
|
||||
{
|
||||
const int originalPosition = textCursor.position();
|
||||
@@ -108,6 +115,8 @@ QTextCursor wordStartCursor(const QTextCursor &textCursor)
|
||||
if (isValidIdentifierChar(c))
|
||||
cursor.movePosition(QTextCursor::PreviousWord);
|
||||
}
|
||||
if (isAfterOperatorKeyword(cursor))
|
||||
cursor.movePosition(QTextCursor::PreviousWord);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
@@ -90,6 +90,20 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static SourceRange getOperatorRange(const CXTranslationUnit tu,
|
||||
const Tokens &tokens,
|
||||
uint operatorIndex)
|
||||
{
|
||||
const CXSourceLocation start = clang_getTokenLocation(tu, tokens.data[operatorIndex]);
|
||||
operatorIndex += 2;
|
||||
while (operatorIndex < tokens.tokenCount
|
||||
&& !(ClangString(clang_getTokenSpelling(tu, tokens.data[operatorIndex])) == "(")) {
|
||||
++operatorIndex;
|
||||
}
|
||||
const CXSourceLocation end = clang_getTokenLocation(tu, tokens.data[operatorIndex]);
|
||||
return SourceRange(clang_getRange(start, end));
|
||||
}
|
||||
|
||||
static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor,
|
||||
const Utf8String &tokenStr)
|
||||
{
|
||||
@@ -99,10 +113,14 @@ static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor,
|
||||
if (!(tokenStr == ClangString(clang_getTokenSpelling(tu, tokens.data[i]))))
|
||||
continue;
|
||||
|
||||
if (cursor.isFunctionLike()
|
||||
&& (i+1 > tokens.tokenCount
|
||||
|| !(ClangString(clang_getTokenSpelling(tu, tokens.data[i+1])) == "("))) {
|
||||
continue;
|
||||
if (cursor.isFunctionLike() || cursor.isConstructorOrDestructor()) {
|
||||
if (tokenStr == "operator")
|
||||
return getOperatorRange(tu, tokens, i);
|
||||
|
||||
if (i+1 > tokens.tokenCount
|
||||
|| !(ClangString(clang_getTokenSpelling(tu, tokens.data[i+1])) == "(")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return SourceRange(clang_getTokenExtent(tu, tokens.data[i]));
|
||||
}
|
||||
|
@@ -351,6 +351,34 @@ TEST_F(FollowSymbol, CursorAfterNamespace)
|
||||
ASSERT_THAT(namespaceDefinition, MatchesFileSourceRange(QString(""), 0, 0, 0));
|
||||
}
|
||||
|
||||
TEST_F(FollowSymbol, CursorOnOneSymbolOperatorDefinition)
|
||||
{
|
||||
const auto namespaceDefinition = followSymbol(76, 13);
|
||||
|
||||
ASSERT_THAT(namespaceDefinition, MatchesSourceRange(72, 9, 9));
|
||||
}
|
||||
|
||||
TEST_F(FollowSymbol, CursorOnTwoSymbolOperatorDefinition)
|
||||
{
|
||||
const auto namespaceDefinition = followSymbol(80, 15);
|
||||
|
||||
ASSERT_THAT(namespaceDefinition, MatchesSourceRange(73, 10, 10));
|
||||
}
|
||||
|
||||
TEST_F(FollowSymbol, CursorOnOneSymbolOperatorDeclaration)
|
||||
{
|
||||
const auto namespaceDefinition = followSymbol(72, 12);
|
||||
|
||||
ASSERT_THAT(namespaceDefinition, MatchesSourceRange(76, 10, 9));
|
||||
}
|
||||
|
||||
TEST_F(FollowSymbol, CursorOnTwoSymbolOperatorDeclaration)
|
||||
{
|
||||
const auto namespaceDefinition = followSymbol(73, 12);
|
||||
|
||||
ASSERT_THAT(namespaceDefinition, MatchesSourceRange(80, 11, 10));
|
||||
}
|
||||
|
||||
std::unique_ptr<Data> FollowSymbol::d;
|
||||
|
||||
void FollowSymbol::SetUpTestCase()
|
||||
|
@@ -65,3 +65,18 @@ FooClass::FooClass() {
|
||||
int main() {
|
||||
return foo() + FooClass::mememember + TEST_DEFINE;
|
||||
}
|
||||
|
||||
class Bar
|
||||
{
|
||||
public:
|
||||
int operator&();
|
||||
Bar& operator[](int);
|
||||
};
|
||||
|
||||
int Bar::operator&() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bar& Bar::operator[](int) {
|
||||
return *this;
|
||||
}
|
||||
|
Reference in New Issue
Block a user