forked from qt-creator/qt-creator
LanguageClient: Improve refactoring markers
Clicking the lightbulb should bring up a menu if and only if there is
more than one possible action for this location.
Amends 089e1edcbf
.
Change-Id: I45348ed4fbf9b3f32e19bbe17f0c2c030ecd24ed
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -1693,12 +1693,11 @@ void ClangdClient::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
|||||||
return;
|
return;
|
||||||
for (const Diagnostic &diagnostic : params.diagnostics()) {
|
for (const Diagnostic &diagnostic : params.diagnostics()) {
|
||||||
const ClangdDiagnostic clangdDiagnostic(diagnostic);
|
const ClangdDiagnostic clangdDiagnostic(diagnostic);
|
||||||
const auto codeActions = clangdDiagnostic.codeActions();
|
auto codeActions = clangdDiagnostic.codeActions();
|
||||||
if (codeActions && !codeActions->isEmpty()) {
|
if (codeActions && !codeActions->isEmpty()) {
|
||||||
for (CodeAction action : *codeActions) {
|
for (CodeAction &action : *codeActions)
|
||||||
action.setDiagnostics({diagnostic});
|
action.setDiagnostics({diagnostic});
|
||||||
LanguageClient::updateCodeActionRefactoringMarker(this, action, uri);
|
LanguageClient::updateCodeActionRefactoringMarker(this, *codeActions, uri);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// We know that there's only one kind of diagnostic for which clangd has
|
// We know that there's only one kind of diagnostic for which clangd has
|
||||||
// a quickfix tweak, so let's not be wasteful.
|
// a quickfix tweak, so let's not be wasteful.
|
||||||
|
@@ -955,13 +955,14 @@ void Client::handleCodeActionResponse(const CodeActionRequest::Response &respons
|
|||||||
log(*error);
|
log(*error);
|
||||||
if (const Utils::optional<CodeActionResult> &result = response.result()) {
|
if (const Utils::optional<CodeActionResult> &result = response.result()) {
|
||||||
if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&*result)) {
|
if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&*result)) {
|
||||||
|
QList<CodeAction> codeActions;
|
||||||
for (const Utils::variant<Command, CodeAction> &item : *list) {
|
for (const Utils::variant<Command, CodeAction> &item : *list) {
|
||||||
if (auto action = Utils::get_if<CodeAction>(&item))
|
if (auto action = Utils::get_if<CodeAction>(&item))
|
||||||
updateCodeActionRefactoringMarker(this, *action, uri);
|
codeActions << *action;
|
||||||
else if (auto command = Utils::get_if<Command>(&item)) {
|
else if (auto command = Utils::get_if<Command>(&item))
|
||||||
Q_UNUSED(command) // todo
|
Q_UNUSED(command) // todo
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
updateCodeActionRefactoringMarker(this, codeActions, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -149,7 +149,7 @@ QTextCursor endOfLineCursor(const QTextCursor &cursor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateCodeActionRefactoringMarker(Client *client,
|
void updateCodeActionRefactoringMarker(Client *client,
|
||||||
const CodeAction &action,
|
const QList<CodeAction> &actions,
|
||||||
const DocumentUri &uri)
|
const DocumentUri &uri)
|
||||||
{
|
{
|
||||||
TextDocument* doc = TextDocument::textDocumentForFilePath(uri.toFilePath());
|
TextDocument* doc = TextDocument::textDocumentForFilePath(uri.toFilePath());
|
||||||
@@ -159,46 +159,59 @@ void updateCodeActionRefactoringMarker(Client *client,
|
|||||||
if (editors.isEmpty())
|
if (editors.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QList<Diagnostic> &diagnostics = action.diagnostics().value_or(QList<Diagnostic>());
|
|
||||||
|
|
||||||
QHash<int, RefactorMarker> markersAtBlock;
|
QHash<int, RefactorMarker> markersAtBlock;
|
||||||
RefactorMarker marker;
|
const auto addMarkerForCursor = [&](const CodeAction &action, const Range &range) {
|
||||||
marker.type = client->id();
|
const QTextCursor cursor = endOfLineCursor(range.start().toTextCursor(doc->document()));
|
||||||
marker.tooltip = LanguageClientManager::tr("Show available quick fixes");
|
const auto it = markersAtBlock.find(cursor.blockNumber());
|
||||||
|
if (it != markersAtBlock.end()) {
|
||||||
auto addMarkerForCursor = [&](const QTextCursor &cursor) {
|
it->tooltip = LanguageClientManager::tr("Show available quick fixes");
|
||||||
if (!markersAtBlock.contains(cursor.blockNumber())) {
|
it->callback = [cursor](TextEditorWidget *editor) {
|
||||||
marker.cursor = cursor;
|
|
||||||
marker.callback = [=](TextEditorWidget *editor) {
|
|
||||||
editor->setTextCursor(cursor);
|
editor->setTextCursor(cursor);
|
||||||
editor->invokeAssist(TextEditor::QuickFix);
|
editor->invokeAssist(TextEditor::QuickFix);
|
||||||
};
|
};
|
||||||
markersAtBlock[cursor.blockNumber()] = marker;
|
return;
|
||||||
}
|
}
|
||||||
|
RefactorMarker marker;
|
||||||
|
marker.type = client->id();
|
||||||
|
marker.cursor = cursor;
|
||||||
|
if (action.isValid())
|
||||||
|
marker.tooltip = action.title();
|
||||||
|
if (action.edit()) {
|
||||||
|
marker.callback = [client, edit = action.edit()](const TextEditorWidget *) {
|
||||||
|
applyWorkspaceEdit(client, *edit);
|
||||||
|
};
|
||||||
|
} else if (action.command()) {
|
||||||
|
marker.callback = [command = action.command(),
|
||||||
|
client = QPointer(client)](const TextEditorWidget *) {
|
||||||
|
if (client)
|
||||||
|
client->executeCommand(*command);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
markersAtBlock[cursor.blockNumber()] = marker;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Utils::optional<WorkspaceEdit> edit = action.edit()) {
|
for (const CodeAction &action : actions) {
|
||||||
if (diagnostics.isEmpty()) {
|
const QList<Diagnostic> &diagnostics = action.diagnostics().value_or(QList<Diagnostic>());
|
||||||
QList<TextEdit> edits;
|
if (Utils::optional<WorkspaceEdit> edit = action.edit()) {
|
||||||
if (optional<QList<TextDocumentEdit>> documentChanges = edit->documentChanges()) {
|
if (diagnostics.isEmpty()) {
|
||||||
QList<TextDocumentEdit> changesForUri = Utils::filtered(
|
QList<TextEdit> edits;
|
||||||
*documentChanges, [uri](const TextDocumentEdit &edit) {
|
if (optional<QList<TextDocumentEdit>> documentChanges = edit->documentChanges()) {
|
||||||
return edit.textDocument().uri() == uri;
|
QList<TextDocumentEdit> changesForUri = Utils::filtered(
|
||||||
});
|
*documentChanges, [uri](const TextDocumentEdit &edit) {
|
||||||
for (const TextDocumentEdit &edit : changesForUri)
|
return edit.textDocument().uri() == uri;
|
||||||
edits << edit.edits();
|
});
|
||||||
} else if (optional<WorkspaceEdit::Changes> localChanges = edit->changes()) {
|
for (const TextDocumentEdit &edit : changesForUri)
|
||||||
edits = (*localChanges)[uri];
|
edits << edit.edits();
|
||||||
}
|
} else if (optional<WorkspaceEdit::Changes> localChanges = edit->changes()) {
|
||||||
for (const TextEdit &edit : qAsConst(edits)) {
|
edits = (*localChanges)[uri];
|
||||||
addMarkerForCursor(
|
}
|
||||||
endOfLineCursor(edit.range().start().toTextCursor(doc->document())));
|
for (const TextEdit &edit : qAsConst(edits))
|
||||||
|
addMarkerForCursor(action, edit.range());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const Diagnostic &diagnostic : diagnostics)
|
||||||
|
addMarkerForCursor(action, diagnostic.range());
|
||||||
}
|
}
|
||||||
for (const Diagnostic &diagnostic : diagnostics)
|
|
||||||
addMarkerForCursor(
|
|
||||||
endOfLineCursor(diagnostic.range().start().toTextCursor(doc->document())));
|
|
||||||
const RefactorMarkers markers = markersAtBlock.values();
|
const RefactorMarkers markers = markersAtBlock.values();
|
||||||
for (BaseTextEditor *editor : editors) {
|
for (BaseTextEditor *editor : editors) {
|
||||||
if (TextEditorWidget *editorWidget = editor->editorWidget())
|
if (TextEditorWidget *editorWidget = editor->editorWidget())
|
||||||
|
@@ -59,7 +59,7 @@ void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextDocumentManipulatorInte
|
|||||||
bool newTextIsSnippet = false);
|
bool newTextIsSnippet = false);
|
||||||
void LANGUAGECLIENT_EXPORT
|
void LANGUAGECLIENT_EXPORT
|
||||||
updateCodeActionRefactoringMarker(Client *client,
|
updateCodeActionRefactoringMarker(Client *client,
|
||||||
const LanguageServerProtocol::CodeAction &action,
|
const QList<LanguageServerProtocol::CodeAction> &actions,
|
||||||
const LanguageServerProtocol::DocumentUri &uri);
|
const LanguageServerProtocol::DocumentUri &uri);
|
||||||
void updateEditorToolBar(Core::IEditor *editor);
|
void updateEditorToolBar(Core::IEditor *editor);
|
||||||
const QIcon LANGUAGECLIENT_EXPORT symbolIcon(int type);
|
const QIcon LANGUAGECLIENT_EXPORT symbolIcon(int type);
|
||||||
|
Reference in New Issue
Block a user