diff --git a/src/plugins/codeeditor/gui/completion/codecompletionmodel.cpp b/src/plugins/codeeditor/gui/completion/codecompletionmodel.cpp index 7e8660f4e..de4c82822 100644 --- a/src/plugins/codeeditor/gui/completion/codecompletionmodel.cpp +++ b/src/plugins/codeeditor/gui/completion/codecompletionmodel.cpp @@ -126,7 +126,11 @@ lsp::Range CodeCompletionModel::range() const if (d->completionDatas.isEmpty()) return {}; - return d->completionDatas.first().textEdit.range; + const auto &item = d->completionDatas.first(); + if (item.textEdit.newText.isEmpty()) + return {}; + + return item.textEdit.range; } lsp::CompletionItem *CodeCompletionModel::item(const QModelIndex &index) const diff --git a/src/plugins/codeeditor/gui/completion/codecompletionwidget.cpp b/src/plugins/codeeditor/gui/completion/codecompletionwidget.cpp index 0e301971f..b051ae559 100644 --- a/src/plugins/codeeditor/gui/completion/codecompletionwidget.cpp +++ b/src/plugins/codeeditor/gui/completion/codecompletionwidget.cpp @@ -160,6 +160,14 @@ void CodeCompletionWidget::executeCompletionItem(const QModelIndex &index) if (!item) return; + if (!item->textEdit.newText.isEmpty()) + executeWithTextEdit(item); + else + executeWithoutTextEdit(item); +} + +void CodeCompletionWidget::executeWithTextEdit(lsp::CompletionItem *item) +{ int labelOpenParenOffset = item->label.indexOf('('); int labelClosingParenOffset = item->label.indexOf(')'); bool isMacroCall = item->kind == lsp::CompletionItem::Text && labelOpenParenOffset != -1 @@ -204,6 +212,30 @@ void CodeCompletionWidget::executeCompletionItem(const QModelIndex &index) } } +void CodeCompletionWidget::executeWithoutTextEdit(lsp::CompletionItem *item) +{ + const int pos = editor()->cursorPosition(); + const QString textToInsert(item->insertText); + int length = 0; + for (auto it = textToInsert.crbegin(), end = textToInsert.crend(); it != end; ++it) { + char character = editor()->SendScintilla(TextEditor::SCI_GETCHARAT, pos - length - 1); + if (it->toLower() != QChar(character).toLower()) { + length = 0; + break; + } + ++length; + } + + int line = editor()->SendScintilla(TextEditor::SCI_LINEFROMPOSITION, pos); + int lineStartPos = editor()->SendScintilla(TextEditor::SCI_POSITIONFROMLINE, line); + const auto &text = editor()->text(lineStartPos, pos); + static QRegularExpression identifier("[a-zA-Z_][a-zA-Z0-9_]*$"); + QRegularExpressionMatch match = identifier.match(text); + int matchLength = match.hasMatch() ? match.capturedLength(0) : 0; + length = qMax(length, matchLength); + editor()->replaceRange(pos - length, pos, textToInsert); +} + void CodeCompletionWidget::modelContentChanged() { if (!editor()->hasFocus()) diff --git a/src/plugins/codeeditor/gui/completion/codecompletionwidget.h b/src/plugins/codeeditor/gui/completion/codecompletionwidget.h index 69fcb270b..4cb37ba72 100644 --- a/src/plugins/codeeditor/gui/completion/codecompletionwidget.h +++ b/src/plugins/codeeditor/gui/completion/codecompletionwidget.h @@ -7,6 +7,10 @@ #include +namespace lsp { +struct CompletionItem; +} + class TextEditor; class CodeCompletionView; class CodeCompletionModel; @@ -48,6 +52,8 @@ public slots: QString filterString(); bool isFunctionKind(int kind); void executeCompletionItem(const QModelIndex &index); + void executeWithTextEdit(lsp::CompletionItem *item); + void executeWithoutTextEdit(lsp::CompletionItem *item); private slots: void modelContentChanged(); diff --git a/src/plugins/cxx/lexer/scilexercpp.cpp b/src/plugins/cxx/lexer/scilexercpp.cpp index 6f5685e01..de22144ca 100644 --- a/src/plugins/cxx/lexer/scilexercpp.cpp +++ b/src/plugins/cxx/lexer/scilexercpp.cpp @@ -389,7 +389,7 @@ const char *SciLexerCPP::keywords(int set) const return "and and_eq asm auto bitand bitor bool break case catch " "char class compl const const_cast continue default " "delete do double dynamic_cast else enum explicit export " - "extern false farcall float for friend goto if inline int " + "extern false farcall final float for friend goto if inline int " "long mutable namespace new not not_eq nullptr null out " "operator or or_eq override private protected public println register " "reinterpret_cast return short signed sizeof static system "