feat: Improve assemble string after code suggestion

This commit is contained in:
Petr Mironychev
2026-04-23 11:14:46 +02:00
parent 42199024ff
commit e86e7e103e
3 changed files with 91 additions and 140 deletions

View File

@@ -9,56 +9,43 @@
namespace QodeAssist {
static QStringList extractTokens(const QString &str)
static bool isClosingTail(const QString &s, int from)
{
QStringList tokens;
QString currentToken;
for (const QChar &ch : str) {
if (ch.isLetterOrNumber() || ch == '_') {
currentToken += ch;
} else {
if (!currentToken.isEmpty() && currentToken.length() > 1) {
tokens.append(currentToken);
}
currentToken.clear();
}
static const QString closeChars = QStringLiteral("(){}[];,");
for (int i = from; i < s.size(); ++i) {
const QChar c = s.at(i);
if (!c.isSpace() && !closeChars.contains(c))
return false;
}
if (!currentToken.isEmpty() && currentToken.length() > 1) {
tokens.append(currentToken);
}
return tokens;
return true;
}
int LLMSuggestion::calculateReplaceLength(const QString &suggestion,
const QString &rightText,
const QString &entireLine)
int LLMSuggestion::calculateReplaceLength(const QString &suggestion, const QString &rightText)
{
if (rightText.isEmpty()) {
if (rightText.isEmpty())
return 0;
const int maxN = qMin(suggestion.size(), rightText.size());
int lcp = 0;
while (lcp < maxN && suggestion.at(lcp) == rightText.at(lcp))
++lcp;
if (lcp > 0) {
if (isClosingTail(rightText, lcp))
return rightText.size();
return lcp;
}
QString structuralChars = "{}[]()<>;,";
bool hasStructuralOverlap = false;
for (const QChar &ch : structuralChars) {
if (suggestion.contains(ch) && rightText.contains(ch)) {
hasStructuralOverlap = true;
break;
}
}
if (hasStructuralOverlap) {
return rightText.length();
}
if (!isClosingTail(rightText, 0))
return 0;
static const QString closeChars = QStringLiteral("(){}[];,");
int i = suggestion.size() - 1;
while (i >= 0 && suggestion.at(i).isSpace())
--i;
if (i >= 0 && closeChars.contains(suggestion.at(i)) && rightText.contains(suggestion.at(i)))
return rightText.size();
const QStringList suggestionTokens = extractTokens(suggestion);
const QStringList lineTokens = extractTokens(entireLine);
for (const auto &token : suggestionTokens) {
if (lineTokens.contains(token)) {
return rightText.length();
}
}
return 0;
}
@@ -82,22 +69,21 @@ LLMSuggestion::LLMSuggestion(
QString rightText = blockText.mid(cursorPositionInBlock);
QString suggestionText = data.text;
QString entireLine = blockText;
if (!suggestionText.contains('\n')) {
int replaceLength = calculateReplaceLength(suggestionText, rightText, entireLine);
int replaceLength = calculateReplaceLength(suggestionText, rightText);
QString remainingRightText = (replaceLength > 0) ? rightText.mid(replaceLength) : rightText;
QString displayText = leftText + suggestionText + remainingRightText;
replacementDocument()->setPlainText(displayText);
} else {
int firstLineEnd = suggestionText.indexOf('\n');
QString firstLine = suggestionText.left(firstLineEnd);
QString restOfCompletion = suggestionText.mid(firstLineEnd);
int replaceLength = calculateReplaceLength(firstLine, rightText, entireLine);
int replaceLength = calculateReplaceLength(firstLine, rightText);
QString remainingRightText = (replaceLength > 0) ? rightText.mid(replaceLength) : rightText;
QString displayText = leftText + firstLine + remainingRightText + restOfCompletion;
replacementDocument()->setPlainText(displayText);
}
@@ -147,10 +133,9 @@ bool LLMSuggestion::applyPart(Part part, TextEditor::TextEditorWidget *widget)
if (startPos == 0) {
QTextBlock currentBlock = cursor.block();
QString textAfterCursor = currentBlock.text().mid(cursor.positionInBlock());
QString entireLine = currentBlock.text();
int replaceLength = calculateReplaceLength(text, textAfterCursor, entireLine);
int replaceLength = calculateReplaceLength(text, textAfterCursor);
if (replaceLength > 0) {
currentCursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, replaceLength);
currentCursor.removeSelectedText();
@@ -200,9 +185,7 @@ bool LLMSuggestion::apply()
QString text = currentData.text;
QTextBlock currentBlock = cursor.block();
QString textBeforeCursor = currentBlock.text().left(cursor.positionInBlock());
QString textAfterCursor = currentBlock.text().mid(cursor.positionInBlock());
QString entireLine = currentBlock.text();
QTextCursor editCursor = cursor;
editCursor.beginEditBlock();
@@ -212,22 +195,22 @@ bool LLMSuggestion::apply()
QString firstLine = text.left(firstLineEnd);
QString restOfText = text.mid(firstLineEnd);
int replaceLength = calculateReplaceLength(firstLine, textAfterCursor, entireLine);
int replaceLength = calculateReplaceLength(firstLine, textAfterCursor);
if (replaceLength > 0) {
editCursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, replaceLength);
editCursor.removeSelectedText();
}
editCursor.insertText(firstLine + restOfText);
} else {
int replaceLength = calculateReplaceLength(text, textAfterCursor, entireLine);
int replaceLength = calculateReplaceLength(text, textAfterCursor);
if (replaceLength > 0) {
editCursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, replaceLength);
editCursor.removeSelectedText();
}
editCursor.insertText(text);
}