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

LSP Completion: Support textEdit

parent 4bd67163
......@@ -333,32 +333,50 @@ public:
return k == LSPCompletionItemKind::Function || k == LSPCompletionItemKind::Method;
}
static bool hasTextEdit(const LSPCompletionItem &i)
{
return !i.textEdit.newText.isEmpty();
}
void executeCompletionItem(KTextEditor::View *view, const KTextEditor::Range &word, const QModelIndex &index) const override
{
if (index.row() < m_matches.size()) {
QChar next = peekNextChar(view->document(), word);
QString matching = m_matches.at(index.row()).insertText;
if (index.row() >= m_matches.size()) {
return;
}
QChar next = peekNextChar(view->document(), word);
QString matching;
KTextEditor::Range replaceRange = word;
const auto &completionItem = m_matches.at(index.row());
if (hasTextEdit(completionItem)) {
matching = completionItem.textEdit.newText;
auto range = completionItem.textEdit.range;
replaceRange = range;
} else {
matching = m_matches.at(index.row()).insertText;
// if there is already a '"' or >, remove it, this happens with #include "xx.h"
if ((next == QLatin1Char('"') && matching.endsWith(QLatin1Char('"'))) || (next == QLatin1Char('>') && matching.endsWith(QLatin1Char('>')))) {
matching.chop(1);
}
}
// This is a function
const auto &m = m_matches.at(index.row());
// add parentheses if function and guestimated meaningful for language in question
// this covers at least the common cases such as clangd, python, etc
// also no need to add one if the next char is already
bool addParens = m_complParens && next != QLatin1Char('(') && isFunctionKind(m.kind) && m_triggersSignature.contains(QLatin1Char('('));
if (addParens) {
matching += QStringLiteral("()");
}
const auto kind = completionItem.kind;
// Is this a function?
// add parentheses if function and guestimated meaningful for language in question
// this covers at least the common cases such as clangd, python, etc
// also no need to add one if the next char is already
bool addParens = m_complParens && next != QLatin1Char('(') && isFunctionKind(kind) && m_triggersSignature.contains(QLatin1Char('('));
if (addParens) {
matching += QStringLiteral("()");
}
view->document()->replaceText(word, matching);
view->document()->replaceText(replaceRange, matching);
if (addParens) {
// place the cursor in between (|)
view->setCursorPosition({view->cursorPosition().line(), view->cursorPosition().column() - 1});
}
if (addParens) {
// place the cursor in between (|)
view->setCursorPosition({view->cursorPosition().line(), view->cursorPosition().column() - 1});
}
}
......
......@@ -195,6 +195,11 @@ struct LSPSymbolInformation {
QList<LSPSymbolInformation> children;
};
struct LSPTextEdit {
LSPRange range;
QString newText;
};
enum class LSPCompletionItemKind {
Text = 1,
Method = 2,
......@@ -230,6 +235,7 @@ struct LSPCompletionItem {
LSPMarkupContent documentation;
QString sortText;
QString insertText;
LSPTextEdit textEdit;
};
struct LSPParameterInformation {
......@@ -258,11 +264,6 @@ struct LSPFormattingOptions {
QJsonObject extra;
};
struct LSPTextEdit {
LSPRange range;
QString newText;
};
enum class LSPDiagnosticSeverity {
Unknown = 0,
Error = 1,
......
......@@ -569,6 +569,13 @@ static QList<LSPCompletionItem> parseDocumentCompletion(const QJsonValue &result
if (items.empty()) {
items = result.toObject().value(QStringLiteral("items")).toArray();
}
auto parseTextEdit = [](const QJsonObject &obj) -> LSPTextEdit {
auto newText = obj.value(QStringLiteral("newText")).toString();
auto range = parseRange(obj.value(QStringLiteral("range")).toObject());
return LSPTextEdit{range, newText};
};
for (const auto &vitem : items) {
const auto &item = vitem.toObject();
auto label = item.value(MEMBER_LABEL).toString();
......@@ -583,7 +590,8 @@ static QList<LSPCompletionItem> parseDocumentCompletion(const QJsonValue &result
insertText = label;
}
auto kind = static_cast<LSPCompletionItemKind>(item.value(MEMBER_KIND).toInt());
ret.push_back({label, kind, detail, doc, sortText, insertText});
auto textEdit = parseTextEdit(item.value(QStringLiteral("textEdit")).toObject());
ret.push_back({label, kind, detail, doc, sortText, insertText, textEdit});
}
return ret;
}
......
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