Skip to content

Commit 06f8efc

Browse files
committed
Fix inline completion when first line has prefix and suffix
1 parent 739cc3c commit 06f8efc

File tree

2 files changed

+33
-43
lines changed

2 files changed

+33
-43
lines changed

plugin/src/de/hetzge/eclipse/aicoder/inline/InlineCompletion.java

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,15 @@ public record InlineCompletion(
1717
int widgetLineIndex,
1818
IRegion modelRegion,
1919
int widgetOffset,
20-
String firstLineContent,
21-
String content,
22-
/*
23-
* if the completion is not the end of the line, this contains the next letter (otherwise null)
24-
*/
25-
String firstLineSuffixCharacter,
20+
String content, // the whole completion content
21+
List<String> lines, // the completion content line by line
22+
String firstLineFillPrefix,
23+
String firstLineFillSuffix,
24+
String firstLineSuffix, // the existing suffix of the line that is being completed
25+
String firstLineSuffixCharacter, // if the completion is not the end of the line, this contains the next letter (otherwise null)
2626
int lineSpacing,
2727
int lineHeight) {
2828

29-
public String toDebugString() {
30-
return """
31-
=========================
32-
lineIndex: %d
33-
modelRegion: %s
34-
widgetOffset: %d
35-
firstLineContent: "%s"
36-
content:
37-
---
38-
%s
39-
---
40-
firstLineSuffixCharacter: "%s"
41-
lineSpacing: %d
42-
lineHeight: %d
43-
=========================
44-
""".formatted(this.widgetLineIndex, this.modelRegion, this.widgetOffset, this.firstLineContent, this.content, this.firstLineSuffixCharacter, this.lineSpacing, this.lineHeight);
45-
}
46-
4729
public void applyTo(final IDocument document) throws BadLocationException {
4830
final int replaceOffset = this.modelRegion().getOffset();
4931
final int replaceLength = this.modelRegion().getLength();
@@ -78,19 +60,21 @@ public static InlineCompletion create(AiCoderHistoryEntry historyEntry, IDocumen
7860
} else {
7961
lineSuffixLength = document.getLength() - modelOffset;
8062
}
81-
final String lineSuffix = document.get(modelOffset, lineSuffixLength);
82-
final String firstLineSuffixCharacter = !lineSuffix.isBlank() && !isMultiline ? lineSuffix.substring(0, 1) : null;
83-
String firstLineContent = content.lines().findFirst().orElse("");
84-
final boolean contentContainsLineSuffix = content.startsWith(lineSuffix);
85-
if (contentContainsLineSuffix) {
86-
content = content.substring(lineSuffixLength);
87-
firstLineContent = firstLineContent.substring(Math.min(lineSuffixLength, firstLineContent.length()));
88-
}
63+
final String firstLineSuffix = document.get(modelOffset, lineSuffixLength);
64+
final String firstLineSuffixCharacter = !firstLineSuffix.isBlank() ? firstLineSuffix.substring(0, 1) : null;
65+
final String firstLineContent = content.lines().findFirst().orElse("");
66+
final boolean contentContainsLineSuffix = content.startsWith(firstLineSuffix);
8967
final int lineSpacing = (int) (defaultLineSpacing + (content.lines().count() - 1) * lineHeight);
90-
final Region modelRegion = new Region(modelOffset, contentContainsLineSuffix || isMultiline ? lineSuffix.length() : 0);
91-
if (isMultiline && !lineSuffix.isBlank()) {
92-
content += lineSuffix;
68+
final Region modelRegion = new Region(modelOffset, contentContainsLineSuffix || isMultiline ? firstLineSuffix.length() : 0);
69+
final String firstLineFillPrefix;
70+
final String firstLineFillSuffix;
71+
if (!firstLineContent.isBlank() && !firstLineSuffix.isBlank() && firstLineContent.contains(firstLineSuffix)) {
72+
firstLineFillPrefix = firstLineContent.substring(0, firstLineContent.indexOf(firstLineSuffix));
73+
firstLineFillSuffix = firstLineContent.substring(firstLineContent.indexOf(firstLineSuffix) + firstLineSuffix.length());
74+
} else {
75+
firstLineFillPrefix = firstLineContent;
76+
firstLineFillSuffix = "";
9377
}
94-
return new InlineCompletion(historyEntry, widgetLine, modelRegion, widgetOffset, firstLineContent, content, firstLineSuffixCharacter, lineSpacing, lineHeight);
78+
return new InlineCompletion(historyEntry, widgetLine, modelRegion, widgetOffset, content, content.lines().toList(), firstLineFillPrefix, firstLineFillSuffix, firstLineSuffix, firstLineSuffixCharacter, lineSpacing, lineHeight);
9579
}
9680
}

plugin/src/de/hetzge/eclipse/aicoder/inline/InlineCompletionController.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,14 +385,18 @@ public void abort(String reason) {
385385
}
386386
if (this.suggestion != null) {
387387
AiCoderActivator.log().info(String.format("Unset suggestion (reason: '%s')", reason));
388-
this.suggestion.historyEntry().setStatus(HistoryStatus.REJECTED);
388+
if (this.suggestion.historyEntry().getStatus() == HistoryStatus.GENERATED) {
389+
this.suggestion.historyEntry().setStatus(HistoryStatus.REJECTED);
390+
}
389391
this.suggestion = null;
390392
AiCoderHistoryView.get().ifPresent(AiCoderHistoryView::refresh);
391393
this.paintListener.resetMetrics();
392394
}
393395
if (this.completion != null) {
394396
AiCoderActivator.log().info(String.format("Unset completions (reason: '%s')", reason));
395-
this.completion.historyEntry().setStatus(HistoryStatus.REJECTED);
397+
if (this.completion.historyEntry().getStatus() == HistoryStatus.GENERATED) {
398+
this.completion.historyEntry().setStatus(HistoryStatus.REJECTED);
399+
}
396400
this.completion = null;
397401
AiCoderHistoryView.get().ifPresent(AiCoderHistoryView::refresh);
398402
this.paintListener.resetMetrics();
@@ -537,24 +541,26 @@ public void paintControl(PaintEvent event) {
537541
final InlineCompletion completion = InlineCompletionController.this.completion;
538542
if (completion != null) {
539543
final Point location = widget.getLocationAtOffset(completion.widgetOffset());
540-
final List<String> lines = completion.content().lines().toList();
544+
final List<String> lines = completion.lines();
541545
event.gc.setBackground(new Color(200, 255, 200));
542546
event.gc.setForeground(widget.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
543547
event.gc.setFont(font);
544548
for (int i = 0; i < lines.size(); i++) {
545549
final String line = lines.get(i);
546550
if (i == 0) {
547551
// first line
548-
event.gc.drawText(completion.firstLineContent(), location.x, location.y, true);
552+
event.gc.drawText(completion.firstLineFillPrefix(), location.x, location.y, true);
549553
if (completion.firstLineSuffixCharacter() != null) {
550554
final int suffixCharacterWidth = event.gc.textExtent(completion.firstLineSuffixCharacter()).x;
551-
final int contentWidth = event.gc.textExtent(completion.firstLineContent()).x;
555+
final int suffixWidth = event.gc.textExtent(completion.firstLineSuffix()).x;
556+
final int fillPrefixWidth = event.gc.textExtent(completion.firstLineFillPrefix()).x;
552557
final StyleRange styleRange = widget.getStyleRangeAtOffset(completion.widgetOffset());
553-
final int metricWidth = contentWidth + suffixCharacterWidth;
558+
final int metricWidth = fillPrefixWidth + suffixCharacterWidth;
554559
if (needMetricUpdate(styleRange, metricWidth)) {
555560
updateMetrics(event, completion, widget, metricWidth);
556561
}
557-
event.gc.drawText(completion.firstLineSuffixCharacter(), location.x + contentWidth, location.y, false);
562+
event.gc.drawText(completion.firstLineSuffixCharacter(), location.x + fillPrefixWidth, location.y, false);
563+
event.gc.drawText(completion.firstLineFillSuffix(), location.x + fillPrefixWidth + suffixWidth, location.y, true);
558564
}
559565
} else {
560566
event.gc.drawText(line.replace("\t", " ".repeat(InlineCompletionController.this.widget.getTabs())), -widget.getHorizontalPixel(), location.y + i * completion.lineHeight(), true);

0 commit comments

Comments
 (0)