Commit d7a0fd63 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

LSP completion: Support additionalTextEdits

`additionalTextEdits` allows for automatical insertion of import/include
statements as required by the completion item you selected.
parent b869c97a
Pipeline #135853 passed with stage
in 5 minutes and 36 seconds
......@@ -187,6 +187,7 @@ class LSPClientCompletionImpl : public LSPClientCompletion
bool m_selectedDocumentation = false;
bool m_signatureHelp = true;
bool m_complParens = true;
bool m_autoImport = true;
QVector<QChar> m_triggersCompletion;
QVector<QChar> m_triggersSignature;
......@@ -233,6 +234,11 @@ public:
m_complParens = s;
}
void setAutoImport(bool s) override
{
m_autoImport = s;
}
QVariant data(const QModelIndex &index, int role) const override
{
if (!index.isValid() || index.row() >= m_matches.size()) {
......@@ -423,6 +429,13 @@ public:
// place the cursor in between (|)
view->setCursorPosition({view->cursorPosition().line(), view->cursorPosition().column() - 1});
}
if (m_autoImport) {
const auto additionalTextEdits = m_matches.at(index.row()).additionalTextEdits;
for (const auto &textEdit : additionalTextEdits) {
view->document()->insertText(textEdit.range.start(), textEdit.newText);
}
}
}
void aborted(KTextEditor::View *view) override
......
......@@ -32,6 +32,7 @@ public:
virtual void setSelectedDocumentation(bool) = 0;
virtual void setSignatureHelp(bool) = 0;
virtual void setCompleteParens(bool) = 0;
virtual void setAutoImport(bool) = 0;
};
#endif
......@@ -46,23 +46,26 @@ LSPClientConfigPage::LSPClientConfigPage(QWidget *parent, LSPClientPlugin *plugi
reset();
for (const auto &cb : {ui->chkSymbolDetails,
ui->chkSymbolExpand,
ui->chkSymbolSort,
ui->chkSymbolTree,
ui->chkComplDoc,
ui->chkRefDeclaration,
ui->chkComplParens,
ui->chkDiagnostics,
ui->chkDiagnosticsMark,
ui->chkDiagnosticsHover,
ui->chkMessages,
ui->chkOnTypeFormatting,
ui->chkIncrementalSync,
ui->chkHighlightGoto,
ui->chkSemanticHighlighting,
ui->chkAutoHover,
ui->chkSignatureHelp}) {
for (const auto &cb : {
ui->chkSymbolDetails,
ui->chkSymbolExpand,
ui->chkSymbolSort,
ui->chkSymbolTree,
ui->chkComplDoc,
ui->chkRefDeclaration,
ui->chkComplParens,
ui->chkDiagnostics,
ui->chkDiagnosticsMark,
ui->chkDiagnosticsHover,
ui->chkMessages,
ui->chkOnTypeFormatting,
ui->chkIncrementalSync,
ui->chkHighlightGoto,
ui->chkSemanticHighlighting,
ui->chkAutoHover,
ui->chkSignatureHelp,
ui->chkAutoImport,
}) {
connect(cb, &QCheckBox::toggled, this, &LSPClientConfigPage::changed);
}
auto ch = [this](int) {
......@@ -138,6 +141,7 @@ void LSPClientConfigPage::apply()
m_plugin->m_highlightGoto = ui->chkHighlightGoto->isChecked();
m_plugin->m_semanticHighlighting = ui->chkSemanticHighlighting->isChecked();
m_plugin->m_signatureHelp = ui->chkSignatureHelp->isChecked();
m_plugin->m_autoImport = ui->chkAutoImport->isChecked();
m_plugin->m_messages = ui->chkMessages->isChecked();
......@@ -178,6 +182,7 @@ void LSPClientConfigPage::reset()
ui->chkHighlightGoto->setChecked(m_plugin->m_highlightGoto);
ui->chkSemanticHighlighting->setChecked(m_plugin->m_semanticHighlighting);
ui->chkSignatureHelp->setChecked(m_plugin->m_signatureHelp);
ui->chkAutoImport->setChecked(m_plugin->m_autoImport);
ui->chkMessages->setChecked(m_plugin->m_messages);
......
......@@ -39,6 +39,7 @@ static const QString CONFIG_MESSAGES{QStringLiteral("Messages")};
static const QString CONFIG_SERVER_CONFIG{QStringLiteral("ServerConfiguration")};
static const QString CONFIG_SEMANTIC_HIGHLIGHTING{QStringLiteral("SemanticHighlighting")};
static const QString CONFIG_SIGNATURE_HELP{QStringLiteral("SignatureHelp")};
static const QString CONFIG_AUTO_IMPORT{QStringLiteral("AutoImport")};
K_PLUGIN_FACTORY_WITH_JSON(LSPClientPluginFactory, "lspclientplugin.json", registerPlugin<LSPClientPlugin>();)
......@@ -110,6 +111,7 @@ void LSPClientPlugin::readConfig()
m_configPath = config.readEntry(CONFIG_SERVER_CONFIG, QUrl());
m_semanticHighlighting = config.readEntry(CONFIG_SEMANTIC_HIGHLIGHTING, false);
m_signatureHelp = config.readEntry(CONFIG_SIGNATURE_HELP, true);
m_autoImport = config.readEntry(CONFIG_AUTO_IMPORT, true);
Q_EMIT update();
}
......@@ -137,6 +139,7 @@ void LSPClientPlugin::writeConfig() const
config.writeEntry(CONFIG_SERVER_CONFIG, m_configPath);
config.writeEntry(CONFIG_SEMANTIC_HIGHLIGHTING, m_semanticHighlighting);
config.writeEntry(CONFIG_SIGNATURE_HELP, m_signatureHelp);
config.writeEntry(CONFIG_AUTO_IMPORT, m_autoImport);
Q_EMIT update();
}
......
......@@ -56,6 +56,7 @@ public:
QUrl m_configPath;
bool m_semanticHighlighting = false;
bool m_signatureHelp = true;
bool m_autoImport = true;
// debug mode?
bool m_debugMode = false;
......
......@@ -1005,6 +1005,9 @@ public:
if (m_messages) {
m_messages->setChecked(m_plugin->m_messages);
}
if (m_completion) {
m_completion->setAutoImport(m_plugin->m_autoImport);
}
displayOptionChanged();
}
......
......@@ -255,6 +255,7 @@ struct LSPCompletionItem {
LSPMarkupContent documentation;
QString sortText;
QString insertText;
QList<LSPTextEdit> additionalTextEdits;
// Intentionally disabled because doesn't work well
// with KTE. See: https://invent.kde.org/utilities/kate/-/merge_requests/438
// LSPTextEdit textEdit;
......
......@@ -470,6 +470,19 @@ static LSPLocation parseLocationLink(const QJsonObject &loc)
return {QUrl(uri), range};
}
static QList<LSPTextEdit> parseTextEdit(const QJsonValue &result)
{
QList<LSPTextEdit> ret;
const auto textEdits = result.toArray();
for (const auto &redit : textEdits) {
auto edit = redit.toObject();
auto text = edit.value(QStringLiteral("newText")).toString();
auto range = parseRange(edit.value(MEMBER_RANGE).toObject());
ret.push_back({range, text});
}
return ret;
}
static LSPDocumentHighlight parseDocumentHighlight(const QJsonValue &result)
{
auto hover = result.toObject();
......@@ -653,7 +666,10 @@ static QList<LSPCompletionItem> parseDocumentCompletion(const QJsonValue &result
}
auto kind = static_cast<LSPCompletionItemKind>(item.value(MEMBER_KIND).toInt());
// auto textEdit = parseTextEdit(item.value(QStringLiteral("textEdit")).toObject());
ret.push_back({label, kind, detail, doc, sortText, insertText /*, textEdit*/});
const auto additionalTextEdits = parseTextEdit(item.value(QStringLiteral("additionalTextEdits")));
ret.push_back({label, kind, detail, doc, sortText, insertText, additionalTextEdits /*, textEdit*/});
}
return ret;
}
......@@ -718,19 +734,6 @@ static QString parseClangdSwitchSourceHeader(const QJsonValue &result)
return result.toString();
}
static QList<LSPTextEdit> parseTextEdit(const QJsonValue &result)
{
QList<LSPTextEdit> ret;
const auto textEdits = result.toArray();
for (const auto &redit : textEdits) {
auto edit = redit.toObject();
auto text = edit.value(QStringLiteral("newText")).toString();
auto range = parseRange(edit.value(MEMBER_RANGE).toObject());
ret.push_back({range, text});
}
return ret;
}
static LSPTextDocumentEdit parseTextDocumentEdit(const QJsonValue &result)
{
LSPTextDocumentEdit ret;
......
......@@ -2,6 +2,14 @@
<ui version="4.0">
<class>LspConfigWidget</class>
<widget class="QWidget" name="LspConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>751</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
......@@ -61,21 +69,21 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Diagnostics:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QCheckBox" name="chkDiagnostics">
<property name="text">
<string>Show program diagnostics</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
<number>20</number>
......@@ -119,70 +127,70 @@
</item>
</layout>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Navigation:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QCheckBox" name="chkRefDeclaration">
<property name="text">
<string>Count declarations when searching for references to a symbol</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QCheckBox" name="chkAutoHover">
<property name="text">
<string>Show information about currently hovered symbol</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QCheckBox" name="chkHighlightGoto">
<property name="text">
<string>Highlight target line when hopping to it</string>
</property>
</widget>
</item>
<item row="10" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Server:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QCheckBox" name="chkMessages">
<property name="text">
<string>Show notifications from the LSP server</string>
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QCheckBox" name="chkIncrementalSync">
<property name="text">
<string>Incrementally synchronize documents with the LSP server</string>
</property>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QCheckBox" name="chkSymbolDetails">
<property name="text">
<string>Display additional details for symbols</string>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="15" column="1">
<widget class="QCheckBox" name="chkSymbolTree">
<property name="text">
<string>Present symbols in a hierarchy instead of a flat list</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="16" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>20</number>
......@@ -199,14 +207,14 @@
</item>
</layout>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="QCheckBox" name="chkSymbolSort">
<property name="text">
<string>Sort symbols alphabetically</string>
</property>
</widget>
</item>
<item row="12" column="0">
<item row="13" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Document outline:</string>
......@@ -227,6 +235,13 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="chkAutoImport">
<property name="text">
<string>Add imports automatically if needed upon completion</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
......@@ -259,8 +274,8 @@
</widget>
</item>
<item>
<widget class="KUrlRequester" name="edtConfigPath">
<property name="text">
<widget class="KUrlRequester" name="edtConfigPath" native="true">
<property name="text" stdset="0">
<string/>
</property>
</widget>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment