LanguageClient: support additional goto targets in symbol support

Allow to follow to the symbol definition as well as to the type
definition for the symbol under the cursor position.

Change-Id: I8ff50b33a1e739f81b0832b1b28ffc525e1f7177
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2023-09-05 11:14:10 +02:00
parent 23828a1d9c
commit 80633a59aa
19 changed files with 265 additions and 106 deletions

View File

@@ -1013,7 +1013,11 @@ void ClangdClient::followSymbol(TextDocument *document,
const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document);
if (followTo == FollowTo::SymbolDef && !resolveTarget) {
symbolSupport().findLinkAt(document, adjustedCursor, callback, false);
symbolSupport().findLinkAt(document,
adjustedCursor,
callback,
false,
LanguageClient::LinkTarget::SymbolDef);
return;
}

View File

@@ -714,7 +714,11 @@ void ClangdFindLocalReferences::Private::findDefinition()
if (sentinel)
getDefinitionAst(l);
};
client()->symbolSupport().findLinkAt(document, cursor, linkHandler, true);
client()->symbolSupport().findLinkAt(document,
cursor,
linkHandler,
true,
LanguageClient::LinkTarget::SymbolDef);
}
void ClangdFindLocalReferences::Private::getDefinitionAst(const Link &link)

View File

@@ -154,7 +154,11 @@ ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &
if (self->d->cursorNode)
self->d->handleGotoDefinitionResult();
};
client->symbolSupport().findLinkAt(document, cursor, std::move(gotoDefCallback), true);
client->symbolSupport().findLinkAt(document,
cursor,
std::move(gotoDefCallback),
true,
LanguageClient::LinkTarget::SymbolDef);
const auto astHandler = [self = QPointer(this)](const ClangdAstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast response for cursor";

View File

@@ -16,8 +16,6 @@ const char G_GLOBAL[] = "CppEditor.GGlobal";
const char CPPEDITOR_ID[] = "CppEditor.C++Editor";
const char SWITCH_DECLARATION_DEFINITION[] = "CppEditor.SwitchDeclarationDefinition";
const char OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT[] = "CppEditor.OpenDeclarationDefinitionInNextSplit";
const char FOLLOW_SYMBOL_TO_TYPE[] = "TextEditor.FollowSymbolToType";
const char FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT[] = "TextEditor.FollowSymbolToTypeInNextSplit";
const char OPEN_PREPROCESSOR_DIALOG[] = "CppEditor.OpenPreprocessorDialog";
const char MULTIPLE_PARSE_CONTEXTS_AVAILABLE[] = "CppEditor.MultipleParseContextsAvailable";
const char M_REFACTORING_MENU_INSERTION_POINT[] = "CppEditor.RefactorGroup";

View File

@@ -152,6 +152,7 @@ public:
| TextEditorActionHandler::UnCommentSelection
| TextEditorActionHandler::UnCollapseAll
| TextEditorActionHandler::FollowSymbolUnderCursor
| TextEditorActionHandler::FollowTypeUnderCursor
| TextEditorActionHandler::RenameSymbol
| TextEditorActionHandler::FindUsage);
}
@@ -336,31 +337,10 @@ void CppEditorPlugin::addPerSymbolActions()
touchBar->addAction(cmd, Core::Constants::G_TOUCHBAR_NAVIGATION);
addSymbolActionToMenus(ActionManager::command(
TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT));
QAction * const followSymbolToType = new QAction(Tr::tr("Follow Symbol Under Cursor to Type"),
this);
cmd = ActionManager::registerAction(followSymbolToType, Constants::FOLLOW_SYMBOL_TO_TYPE,
context, true);
cmd->setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+F2")));
connect(followSymbolToType, &QAction::triggered, this, []{
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
editorWidget->followSymbolToType(false);
});
addSymbolActionToMenus(cmd);
QAction * const followSymbolToTypeInNextSplit =
new QAction(Tr::tr("Follow Symbol to Type in Next Split"), this);
cmd = ActionManager::registerAction(followSymbolToTypeInNextSplit,
Constants::FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT,
context, true);
cmd->setDefaultKeySequence(QKeySequence(HostOsInfo::isMacHost()
? Tr::tr("Meta+E, Ctrl+Shift+F2")
: Tr::tr("Ctrl+E, Ctrl+Shift+F2")));
connect(followSymbolToTypeInNextSplit, &QAction::triggered, this, []{
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
editorWidget->followSymbolToType(true);
});
addSymbolActionToMenus(cmd);
addSymbolActionToMenus(ActionManager::command(
TextEditor::Constants::FOLLOW_SYMBOL_TO_TYPE));
addSymbolActionToMenus(ActionManager::command(
TextEditor::Constants::FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT));
QAction * const switchDeclarationDefinition
= new QAction(Tr::tr("Switch Between Function Declaration/Definition"), this);

View File

@@ -893,20 +893,6 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
CppModelManager::switchDeclDef(cursor, std::move(callback));
}
void CppEditorWidget::followSymbolToType(bool inNextSplit)
{
if (!CppModelManager::instance())
return;
const CursorInEditor cursor(textCursor(), textDocument()->filePath(), this, textDocument());
const auto callback = [self = QPointer(this),
split = inNextSplit != alwaysOpenLinksInNextSplit()](const Link &link) {
if (self && link.hasValidTarget())
self->openLink(link, split);
};
CppModelManager::followSymbolToType(cursor, callback, inNextSplit);
}
bool CppEditorWidget::followUrl(const QTextCursor &cursor,
const Utils::LinkHandler &processLinkCallback)
{
@@ -997,13 +983,29 @@ void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
}
callback(link);
};
CppModelManager::followSymbol(
CursorInEditor{cursor, filePath, this, textDocument()},
CppModelManager::followSymbol(CursorInEditor{cursor, filePath, this, textDocument()},
callbackWrapper,
resolveTarget,
inNextSplit);
}
void CppEditorWidget::findTypeAt(const QTextCursor &cursor,
const Utils::LinkHandler &processLinkCallback,
bool resolveTarget,
bool inNextSplit)
{
if (!CppModelManager::instance())
return;
const CursorInEditor cursorInEditor(cursor, textDocument()->filePath(), this, textDocument());
const auto callback = [self = QPointer(this),
split = inNextSplit != alwaysOpenLinksInNextSplit()](const Link &link) {
if (self && link.hasValidTarget())
self->openLink(link, split);
};
CppModelManager::followSymbolToType(cursorInEditor, callback, inNextSplit);
}
unsigned CppEditorWidget::documentRevision() const
{
return document()->revision();

View File

@@ -57,7 +57,6 @@ public:
void selectAll() override;
void switchDeclarationDefinition(bool inNextSplit);
void followSymbolToType(bool inNextSplit);
void showPreProcessorWidget();
void findUsages() override;
@@ -105,6 +104,11 @@ protected:
bool resolveTarget = true,
bool inNextSplit = false) override;
void findTypeAt(const QTextCursor &cursor,
const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false) override;
void slotCodeStyleSettingsChanged(const QVariant &) override;
private:

View File

@@ -936,6 +936,10 @@ void Client::activateEditor(Core::IEditor *editor)
optionalActions |= TextEditor::TextEditorActionHandler::FindUsage;
if (symbolSupport().supportsRename(widget->textDocument()))
optionalActions |= TextEditor::TextEditorActionHandler::RenameSymbol;
if (symbolSupport().supportsFindLink(widget->textDocument(), LinkTarget::SymbolDef))
optionalActions |= TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor;
if (symbolSupport().supportsFindLink(widget->textDocument(), LinkTarget::SymbolTypeDef))
optionalActions |= TextEditor::TextEditorActionHandler::FollowTypeUnderCursor;
if (CallHierarchyFactory::supportsCallHierarchy(this, textEditor->document()))
optionalActions |= TextEditor::TextEditorActionHandler::CallHierarchy;
widget->setOptionalActions(optionalActions);
@@ -1306,7 +1310,8 @@ SymbolSupport &Client::symbolSupport()
void Client::findLinkAt(TextEditor::TextDocument *document,
const QTextCursor &cursor,
Utils::LinkHandler callback,
const bool resolveTarget)
const bool resolveTarget,
LinkTarget target)
{
if (d->m_runningFindLinkRequest.isValid())
cancelRequest(d->m_runningFindLinkRequest);
@@ -1317,7 +1322,8 @@ void Client::findLinkAt(TextEditor::TextDocument *document,
d->m_runningFindLinkRequest = {};
callback(link);
},
resolveTarget);
resolveTarget,
target);
}
void Client::requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,

View File

@@ -4,6 +4,7 @@
#pragma once
#include "languageclient_global.h"
#include "languageclientsymbolsupport.h"
#include "languageclientutils.h"
#include "semantichighlightsupport.h"
@@ -45,7 +46,6 @@ class LanguageClientOutlineItem;
class LanguageClientQuickFixProvider;
class LanguageFilter;
class ProgressManager;
class SymbolSupport;
class LANGUAGECLIENT_EXPORT Client : public QObject
{
@@ -157,7 +157,8 @@ public:
void findLinkAt(TextEditor::TextDocument *document,
const QTextCursor &cursor,
Utils::LinkHandler callback,
const bool resolveTarget);
const bool resolveTarget,
LinkTarget target);
DocumentSymbolCache *documentSymbolCache();
HoverHandler *hoverHandler();
QList<LanguageServerProtocol::Diagnostic> diagnosticsAt(const Utils::FilePath &filePath,

View File

@@ -479,8 +479,24 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
connect(widget, &TextEditorWidget::requestLinkAt, this,
[document = textEditor->textDocument()]
(const QTextCursor &cursor, const Utils::LinkHandler &callback, bool resolveTarget) {
if (auto client = clientForDocument(document))
client->findLinkAt(document, cursor, callback, resolveTarget);
if (auto client = clientForDocument(document)) {
client->findLinkAt(document,
cursor,
callback,
resolveTarget,
LinkTarget::SymbolDef);
}
});
connect(widget, &TextEditorWidget::requestTypeAt, this,
[document = textEditor->textDocument()]
(const QTextCursor &cursor, const Utils::LinkHandler &callback, bool resolveTarget) {
if (auto client = clientForDocument(document)) {
client->findLinkAt(document,
cursor,
callback,
resolveTarget,
LinkTarget::SymbolTypeDef);
}
});
connect(widget, &TextEditorWidget::requestUsages, this,
[document = textEditor->textDocument()](const QTextCursor &cursor) {

View File

@@ -77,15 +77,14 @@ SymbolSupport::SymbolSupport(Client *client)
{}
template<typename Request>
static void sendTextDocumentPositionParamsRequest(Client *client,
const Request &request,
const DynamicCapabilities &dynamicCapabilities,
const ServerCapabilities &serverCapability)
static MessageId sendTextDocumentPositionParamsRequest(Client *client, const Request &request)
{
if (!request.isValid(nullptr))
return;
return {};
const DocumentUri uri = request.params().value().textDocument().uri();
const bool supportedFile = client->isSupportedUri(uri);
const DynamicCapabilities dynamicCapabilities = client->dynamicCapabilities();
const ServerCapabilities serverCapability = client->capabilities();
bool sendMessage = dynamicCapabilities.isRegistered(Request::methodName).value_or(false);
if (sendMessage) {
const TextDocumentRegistrationOptions option(
@@ -102,11 +101,14 @@ static void sendTextDocumentPositionParamsRequest(Client *client,
if (sendMessage && std::holds_alternative<bool>(*provider))
sendMessage = std::get<bool>(*provider);
}
if (sendMessage)
if (sendMessage) {
client->sendMessage(request);
return request.id();
}
return {};
}
static void handleGotoDefinitionResponse(const GotoDefinitionRequest::Response &response,
static void handleGotoResponse(const GotoDefinitionRequest::Response &response,
Utils::LinkHandler callback,
std::optional<Utils::Link> linkUnderCursor,
const Client *client)
@@ -137,14 +139,69 @@ static TextDocumentPositionParams generateDocPosParams(TextEditor::TextDocument
return TextDocumentPositionParams(documentId, pos);
}
template<typename Request>
static MessageId sendGotoRequest(TextEditor::TextDocument *document,
const QTextCursor &cursor,
Utils::LinkHandler callback,
Client *client,
std::optional<Utils::Link> linkUnderCursor)
{
Request request(generateDocPosParams(document, cursor, client));
request.setResponseCallback([callback, linkUnderCursor, client](
const GotoDefinitionRequest::Response &response) {
handleGotoResponse(response, callback, linkUnderCursor, client);
});
return sendTextDocumentPositionParamsRequest(client, request);
return request.id();
}
bool SymbolSupport::supportsFindLink(TextEditor::TextDocument *document, LinkTarget target) const
{
const DocumentUri uri = m_client->hostPathToServerUri(document->filePath());
const DynamicCapabilities dynamicCapabilities = m_client->dynamicCapabilities();
const ServerCapabilities serverCapability = m_client->capabilities();
QString methodName;
std::optional<std::variant<bool, ServerCapabilities::RegistrationOptions>> provider;
switch (target) {
case LinkTarget::SymbolDef:
methodName = GotoDefinitionRequest::methodName;
provider = serverCapability.definitionProvider();
break;
case LinkTarget::SymbolTypeDef:
methodName = GotoTypeDefinitionRequest::methodName;
provider = serverCapability.typeDefinitionProvider();
break;
case LinkTarget::SymbolImplementation:
methodName = GotoImplementationRequest::methodName;
provider = serverCapability.implementationProvider();
break;
}
if (methodName.isEmpty())
return false;
bool supported = dynamicCapabilities.isRegistered(methodName).value_or(false);
if (supported) {
const TextDocumentRegistrationOptions option(dynamicCapabilities.option(methodName));
if (option.isValid())
supported = option.filterApplies(
Utils::FilePath::fromString(QUrl(uri).adjusted(QUrl::PreferLocalFile).toString()));
else
supported = m_client->isSupportedUri(uri);
} else {
supported = provider.has_value();
if (supported && std::holds_alternative<bool>(*provider))
supported = std::get<bool>(*provider);
}
return supported;
}
MessageId SymbolSupport::findLinkAt(TextEditor::TextDocument *document,
const QTextCursor &cursor,
Utils::LinkHandler callback,
const bool resolveTarget)
const bool resolveTarget,
const LinkTarget target)
{
if (!m_client->reachable())
return {};
GotoDefinitionRequest request(generateDocPosParams(document, cursor, m_client));
std::optional<Utils::Link> linkUnderCursor;
if (!resolveTarget) {
QTextCursor linkCursor = cursor;
@@ -156,16 +213,29 @@ MessageId SymbolSupport::findLinkAt(TextEditor::TextDocument *document,
link.linkTextEnd = linkCursor.selectionEnd();
linkUnderCursor = link;
}
request.setResponseCallback([callback, linkUnderCursor, client = m_client](
const GotoDefinitionRequest::Response &response) {
handleGotoDefinitionResponse(response, callback, linkUnderCursor, client);
});
sendTextDocumentPositionParamsRequest(m_client,
request,
m_client->dynamicCapabilities(),
m_client->capabilities());
return request.id();
const TextDocumentPositionParams params = generateDocPosParams(document, cursor, m_client);
switch (target) {
case LinkTarget::SymbolDef:
return sendGotoRequest<GotoDefinitionRequest>(document,
cursor,
callback,
m_client,
linkUnderCursor);
case LinkTarget::SymbolTypeDef:
return sendGotoRequest<GotoTypeDefinitionRequest>(document,
cursor,
callback,
m_client,
linkUnderCursor);
case LinkTarget::SymbolImplementation:
return sendGotoRequest<GotoImplementationRequest>(document,
cursor,
callback,
m_client,
linkUnderCursor);
}
return {};
}
bool SymbolSupport::supportsFindUsages(TextEditor::TextDocument *document) const
@@ -317,10 +387,7 @@ std::optional<MessageId> SymbolSupport::findUsages(TextEditor::TextDocument *doc
handleFindReferencesResponse(response, wordUnderCursor, handler);
});
sendTextDocumentPositionParamsRequest(m_client,
request,
m_client->dynamicCapabilities(),
m_client->capabilities());
sendTextDocumentPositionParamsRequest(m_client, request);
return request.id();
}

View File

@@ -19,16 +19,19 @@ namespace LanguageServerProtocol { class MessageId; }
namespace LanguageClient {
class Client;
enum class LinkTarget { SymbolDef, SymbolTypeDef, SymbolImplementation };
class LANGUAGECLIENT_EXPORT SymbolSupport : public QObject
{
public:
explicit SymbolSupport(Client *client);
bool supportsFindLink(TextEditor::TextDocument *document, LinkTarget target) const;
LanguageServerProtocol::MessageId findLinkAt(TextEditor::TextDocument *document,
const QTextCursor &cursor,
Utils::LinkHandler callback,
const bool resolveTarget);
const bool resolveTarget,
const LinkTarget target);
bool supportsFindUsages(TextEditor::TextDocument *document) const;
using ResultHandler = std::function<void(const QList<LanguageServerProtocol::Location> &)>;

View File

@@ -757,7 +757,11 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor,
bool /*inNextSplit*/)
{
if (auto client = getQmllsClient(textDocument()->filePath())) {
client->findLinkAt(textDocument(), cursor, processLinkCallback, resolveTarget);
client->findLinkAt(textDocument(),
cursor,
processLinkCallback,
resolveTarget,
LanguageClient::LinkTarget::SymbolDef);
return;
}

View File

@@ -48,8 +48,7 @@ PlainTextEditorFactory::PlainTextEditorFactory()
setEditorActionHandlers(TextEditorActionHandler::Format |
TextEditorActionHandler::UnCommentSelection |
TextEditorActionHandler::UnCollapseAll |
TextEditorActionHandler::FollowSymbolUnderCursor);
TextEditorActionHandler::UnCollapseAll);
}
PlainTextEditorFactory *PlainTextEditorFactory::instance()

View File

@@ -717,6 +717,7 @@ public:
KSyntaxHighlighting::Definition currentDefinition();
void rememberCurrentSyntaxDefinition();
void openLinkUnderCursor(bool openInNextSplit);
void openTypeUnderCursor(bool openInNextSplit);
qreal charWidth() const;
public:
@@ -2446,6 +2447,16 @@ void TextEditorWidget::openLinkUnderCursorInNextSplit()
d->openLinkUnderCursor(!alwaysOpenLinksInNextSplit());
}
void TextEditorWidget::openTypeUnderCursor()
{
d->openTypeUnderCursor(alwaysOpenLinksInNextSplit());
}
void TextEditorWidget::openTypeUnderCursorInNextSplit()
{
d->openTypeUnderCursor(!alwaysOpenLinksInNextSplit());
}
void TextEditorWidget::findUsages()
{
emit requestUsages(textCursor());
@@ -3642,11 +3653,26 @@ void TextEditorWidgetPrivate::rememberCurrentSyntaxDefinition()
void TextEditorWidgetPrivate::openLinkUnderCursor(bool openInNextSplit)
{
q->findLinkAt(q->textCursor(),
q->findLinkAt(
q->textCursor(),
[openInNextSplit, self = QPointer<TextEditorWidget>(q)](const Link &symbolLink) {
if (self)
self->openLink(symbolLink, openInNextSplit);
}, true, openInNextSplit);
},
true,
openInNextSplit);
}
void TextEditorWidgetPrivate::openTypeUnderCursor(bool openInNextSplit)
{
q->findTypeAt(
q->textCursor(),
[openInNextSplit, self = QPointer<TextEditorWidget>(q)](const Link &symbolLink) {
if (self)
self->openLink(symbolLink, openInNextSplit);
},
true,
openInNextSplit);
}
qreal TextEditorWidgetPrivate::charWidth() const
@@ -6682,6 +6708,14 @@ void TextEditorWidget::findLinkAt(const QTextCursor &cursor,
emit requestLinkAt(cursor, callback, resolveTarget, inNextSplit);
}
void TextEditorWidget::findTypeAt(const QTextCursor &cursor,
const Utils::LinkHandler &callback,
bool resolveTarget,
bool inNextSplit)
{
emit requestTypeAt(cursor, callback, resolveTarget, inNextSplit);
}
bool TextEditorWidget::openLink(const Utils::Link &link, bool inNextSplit)
{
#ifdef WITH_TESTS
@@ -8394,20 +8428,30 @@ void TextEditorWidget::setupFallBackEditor(Id id)
void TextEditorWidget::appendStandardContextMenuActions(QMenu *menu)
{
if (optionalActions() & TextEditorActionHandler::FollowSymbolUnderCursor) {
const auto action = ActionManager::command(Constants::FOLLOW_SYMBOL_UNDER_CURSOR)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::FollowTypeUnderCursor) {
const auto action = ActionManager::command(Constants::FOLLOW_SYMBOL_TO_TYPE)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::FindUsage) {
const auto findUsage = ActionManager::command(Constants::FIND_USAGES)->action();
if (!menu->actions().contains(findUsage))
menu->addAction(findUsage);
const auto action = ActionManager::command(Constants::FIND_USAGES)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::RenameSymbol) {
const auto renameSymbol = ActionManager::command(Constants::RENAME_SYMBOL)->action();
if (!menu->actions().contains(renameSymbol))
menu->addAction(renameSymbol);
const auto action = ActionManager::command(Constants::RENAME_SYMBOL)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::CallHierarchy) {
const auto callHierarchy = ActionManager::command(Constants::OPEN_CALL_HIERARCHY)->action();
if (!menu->actions().contains(callHierarchy))
menu->addAction(callHierarchy);
const auto action = ActionManager::command(Constants::OPEN_CALL_HIERARCHY)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
menu->addSeparator();

View File

@@ -154,7 +154,6 @@ private:
Internal::BaseTextEditorPrivate *d;
};
class TEXTEDITOR_EXPORT TextEditorWidget : public QPlainTextEdit
{
Q_OBJECT
@@ -438,6 +437,8 @@ public:
void openLinkUnderCursor();
void openLinkUnderCursorInNextSplit();
void openTypeUnderCursor();
void openTypeUnderCursorInNextSplit();
virtual void findUsages();
virtual void renameSymbolUnderCursor();
@@ -496,6 +497,8 @@ signals:
void requestLinkAt(const QTextCursor &cursor, const Utils::LinkHandler &callback,
bool resolveTarget, bool inNextSplit);
void requestTypeAt(const QTextCursor &cursor, const Utils::LinkHandler &callback,
bool resolveTarget, bool inNextSplit);
void requestUsages(const QTextCursor &cursor);
void requestRename(const QTextCursor &cursor);
void requestCallHierarchy(const QTextCursor &cursor);
@@ -588,6 +591,11 @@ protected:
bool resolveTarget = true,
bool inNextSplit = false);
virtual void findTypeAt(const QTextCursor &,
const Utils::LinkHandler &processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false);
/*!
Returns whether the link was opened successfully.
*/

View File

@@ -118,6 +118,8 @@ public:
QAction *m_unfoldAllAction = nullptr;
QAction *m_followSymbolAction = nullptr;
QAction *m_followSymbolInNextSplitAction = nullptr;
QAction *m_followToTypeAction = nullptr;
QAction *m_followToTypeInNextSplitAction = nullptr;
QAction *m_findUsageAction = nullptr;
QAction *m_openCallHierarchyAction = nullptr;
QAction *m_renameSymbolAction = nullptr;
@@ -224,6 +226,12 @@ void TextEditorActionHandlerPrivate::createActions()
m_followSymbolInNextSplitAction = registerAction(FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT,
[] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, Tr::tr("Follow Symbol Under Cursor in Next Split"),
QKeySequence(Utils::HostOsInfo::isMacHost() ? Tr::tr("Meta+E, F2") : Tr::tr("Ctrl+E, F2")));
m_followToTypeAction = registerAction(FOLLOW_SYMBOL_TO_TYPE,
[] (TextEditorWidget *w) { w->openTypeUnderCursor(); }, true, Tr::tr("Follow Type Under Cursor"),
QKeySequence(Tr::tr("Ctrl+Shift+F2")));
m_followToTypeInNextSplitAction = registerAction(FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT,
[] (TextEditorWidget *w) { w->openTypeUnderCursorInNextSplit(); }, true, Tr::tr("Follow Type Under Cursor in Next Split"),
QKeySequence(Utils::HostOsInfo::isMacHost() ? Tr::tr("Meta+E, Shift+F2") : Tr::tr("Ctrl+E, Ctrl+Shift+F2")));
m_findUsageAction = registerAction(FIND_USAGES,
[] (TextEditorWidget *w) { w->findUsages(); }, true, Tr::tr("Find References to Symbol Under Cursor"),
QKeySequence(Tr::tr("Ctrl+Shift+U")));
@@ -492,6 +500,10 @@ void TextEditorActionHandlerPrivate::updateOptionalActions()
optionalActions & TextEditorActionHandler::FollowSymbolUnderCursor);
m_followSymbolInNextSplitAction->setEnabled(
optionalActions & TextEditorActionHandler::FollowSymbolUnderCursor);
m_followToTypeAction->setEnabled(
optionalActions & TextEditorActionHandler::FollowTypeUnderCursor);
m_followToTypeInNextSplitAction->setEnabled(
optionalActions & TextEditorActionHandler::FollowTypeUnderCursor);
m_findUsageAction->setEnabled(
optionalActions & TextEditorActionHandler::FindUsage);
m_jumpToFileAction->setEnabled(

View File

@@ -34,10 +34,11 @@ public:
UnCommentSelection = 2,
UnCollapseAll = 4,
FollowSymbolUnderCursor = 8,
JumpToFileUnderCursor = 16,
RenameSymbol = 32,
FindUsage = 64,
CallHierarchy = 128
FollowTypeUnderCursor = 16,
JumpToFileUnderCursor = 32,
RenameSymbol = 64,
FindUsage = 128,
CallHierarchy = 256
};
using TextEditorWidgetResolver = std::function<TextEditorWidget *(Core::IEditor *)>;

View File

@@ -206,6 +206,8 @@ const char INDENT[] = "TextEditor.Indent";
const char UNINDENT[] = "TextEditor.Unindent";
const char FOLLOW_SYMBOL_UNDER_CURSOR[] = "TextEditor.FollowSymbolUnderCursor";
const char FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT[] = "TextEditor.FollowSymbolUnderCursorInNextSplit";
const char FOLLOW_SYMBOL_TO_TYPE[] = "TextEditor.FollowSymbolToType";
const char FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT[] = "TextEditor.FollowSymbolToTypeInNextSplit";
const char FIND_USAGES[] = "TextEditor.FindUsages";
// moved from CppEditor to TextEditor avoid breaking the setting by using the old key
const char RENAME_SYMBOL[] = "CppEditor.RenameSymbolUnderCursor";