Skip to content

Commit faa503e

Browse files
authored
Determine and send inline completion session result (#323)
1 parent 9d818a8 commit faa503e

File tree

9 files changed

+344
-28
lines changed

9 files changed

+344
-28
lines changed

plugin/META-INF/MANIFEST.MF

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.31.0",
2525
org.eclipse.jetty.util;bundle-version="12.0.9",
2626
org.eclipse.core.net;bundle-version="1.5.400",
2727
org.apache.commons.logging;bundle-version="1.2.0",
28-
slf4j.api;bundle-version="2.0.13"
28+
slf4j.api;bundle-version="2.0.13",
29+
org.apache.commons.lang3;bundle-version="3.14.0"
2930
Bundle-Classpath: target/classes/,
3031
target/dependency/annotations-2.28.26.jar,
3132
target/dependency/apache-client-2.28.26.jar,

plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QAcceptSuggestionsHandler.java

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public final synchronized Object execute(final ExecutionEvent event) throws Exec
2525
var suggestion = QInvocationSession.getInstance().getCurrentSuggestion();
2626
var widget = QInvocationSession.getInstance().getViewer().getTextWidget();
2727
var session = QInvocationSession.getInstance();
28+
// mark current suggestion as accepted
29+
session.setAccepted(suggestion.getItemId());
2830
session.setSuggestionAccepted(true);
2931
session.transitionToDecisionMade();
3032
Display display = widget.getDisplay();

plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/AmazonQLspServer.java

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import software.aws.toolkits.eclipse.amazonq.lsp.model.GetConfigurationFromServerParams;
2323
import software.aws.toolkits.eclipse.amazonq.lsp.model.InlineCompletionParams;
2424
import software.aws.toolkits.eclipse.amazonq.lsp.model.InlineCompletionResponse;
25+
import software.aws.toolkits.eclipse.amazonq.lsp.model.LogInlineCompletionSessionResultsParams;
2526
import software.aws.toolkits.eclipse.amazonq.lsp.model.LspServerConfigurations;
2627
import software.aws.toolkits.eclipse.amazonq.lsp.model.UpdateCredentialsPayload;
2728

@@ -30,6 +31,9 @@ public interface AmazonQLspServer extends LanguageServer {
3031
@JsonRequest("aws/textDocument/inlineCompletionWithReferences")
3132
CompletableFuture<InlineCompletionResponse> inlineCompletionWithReferences(InlineCompletionParams params);
3233

34+
@JsonNotification("aws/logInlineCompletionSessionResults")
35+
void logInlineCompletionSessionResult(LogInlineCompletionSessionResultsParams params);
36+
3337
@JsonRequest("aws/chat/sendChatPrompt")
3438
CompletableFuture<String> sendChatPrompt(EncryptedChatParams encryptedChatRequestParams);
3539

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.eclipse.amazonq.lsp.model;
5+
6+
public final class InlineCompletionStates {
7+
// Indicates if suggestion has been seen by the user in the UI
8+
private boolean seen;
9+
// Indicates if suggestion accepted
10+
private boolean accepted;
11+
// Indicates if suggestion was filtered out on the client-side and marked as
12+
// discarded.
13+
private boolean discarded;
14+
15+
public boolean isSeen() {
16+
return seen;
17+
}
18+
19+
public void setSeen(final boolean seen) {
20+
this.seen = seen;
21+
}
22+
23+
public boolean isAccepted() {
24+
return accepted;
25+
}
26+
27+
public void setAccepted(final boolean accepted) {
28+
this.accepted = accepted;
29+
}
30+
31+
public boolean isDiscarded() {
32+
return discarded;
33+
}
34+
35+
public void setDiscarded(final boolean discarded) {
36+
this.discarded = discarded;
37+
}
38+
39+
@Override
40+
public String toString() {
41+
return String.format("{accepted=%b, seen=%b, discarded=%b}", accepted, seen, discarded);
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.eclipse.amazonq.lsp.model;
5+
6+
import java.util.concurrent.ConcurrentHashMap;
7+
8+
import com.fasterxml.jackson.annotation.JsonInclude;
9+
10+
public final class LogInlineCompletionSessionResultsParams {
11+
// Session Id attached to get completion items response
12+
private final String sessionId;
13+
// Map with results of interaction with completion items/suggestions in the UI
14+
private final ConcurrentHashMap<String, InlineCompletionStates> completionSessionResult;
15+
16+
// Total time when items from this suggestion session were visible in UI
17+
@JsonInclude(JsonInclude.Include.NON_NULL)
18+
private Long totalSessionDisplayTime;
19+
// Time from request invocation start to rendering of the first suggestion in the UI.
20+
@JsonInclude(JsonInclude.Include.NON_NULL)
21+
private Long firstCompletionDisplayLatency;
22+
// Length of additional characters inputed by user from when the trigger happens to when the first suggestion is about to be shown in UI
23+
@JsonInclude(JsonInclude.Include.NON_NULL)
24+
private Integer typeaheadLength;
25+
26+
public LogInlineCompletionSessionResultsParams(final String sessionId, final ConcurrentHashMap<String, InlineCompletionStates> completionSessionResult) {
27+
this.sessionId = sessionId;
28+
this.completionSessionResult = completionSessionResult;
29+
}
30+
31+
public Long getTotalSessionDisplayTime() {
32+
return totalSessionDisplayTime;
33+
}
34+
35+
public void setTotalSessionDisplayTime(final Long totalSessionDisplayTime) {
36+
this.totalSessionDisplayTime = totalSessionDisplayTime;
37+
}
38+
39+
public Long getFirstCompletionDisplayLatency() {
40+
return firstCompletionDisplayLatency;
41+
}
42+
43+
public void setFirstCompletionDisplayLatency(final Long firstCompletionDisplayLatency) {
44+
this.firstCompletionDisplayLatency = firstCompletionDisplayLatency;
45+
}
46+
47+
public Integer getTypeaheadLength() {
48+
return typeaheadLength;
49+
}
50+
51+
public void setTypeaheadLength(final Integer typeaheadLength) {
52+
this.typeaheadLength = typeaheadLength;
53+
}
54+
55+
public ConcurrentHashMap<String, InlineCompletionStates> getCompletionSessionResult() {
56+
return completionSessionResult;
57+
}
58+
59+
public String getSessionId() {
60+
return sessionId;
61+
}
62+
63+
}

plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInlineInputListener.java

+24-2
Original file line numberDiff line numberDiff line change
@@ -274,18 +274,33 @@ public void documentChanged(final DocumentEvent event) {
274274
}
275275
String currentSuggestion = session.getCurrentSuggestion().getInsertText();
276276
int currentOffset = widget.getCaretOffset();
277+
277278
if (input.isEmpty()) {
278279
if (distanceTraversed <= 0) {
280+
// discard all suggestions as caret position is less than request invocation position
281+
session.updateCompletionStates(new ArrayList<String>());
279282
session.transitionToDecisionMade();
280283
session.end();
281284
return;
282285
}
283286
distanceTraversed = typeaheadProcessor.getNewDistanceTraversedOnDeleteAndUpdateBracketState(
284287
event.getLength(), distanceTraversed, brackets);
285288
if (distanceTraversed < 0) {
289+
// discard all suggestions as caret position is less than request invocation position
290+
session.updateCompletionStates(new ArrayList<String>());
286291
session.transitionToDecisionMade();
287292
session.end();
288293
}
294+
295+
// note: distanceTraversed as 0 is currently understood to be when a user presses BS removing any typeahead
296+
if (distanceTraversed == 0) {
297+
// reset completion states for all suggestions when user reverts to request
298+
// invocation state
299+
session.resetCompletionStates();
300+
// mark currently displayed suggestion as seen
301+
session.markSuggestionAsSeen();
302+
}
303+
289304
return;
290305
}
291306

@@ -328,12 +343,19 @@ public void documentChanged(final DocumentEvent event) {
328343
session.transitionToDecisionMade(lineToUnsetIndent);
329344
Display.getCurrent().asyncExec(() -> {
330345
if (session.isActive()) {
331-
session.end();
346+
// discard suggestions and end immediately as typeahead does not match
347+
session.updateCompletionStates(new ArrayList<String>());
348+
session.endImmediately();
332349
}
333350
});
334351
return;
335352
}
336353

354+
// discard all other suggestions except for current one as typeahead matches it
355+
// also mark current one as seen as it continues to be displayed
356+
session.updateCompletionStates(List.of(session.getCurrentSuggestion().getItemId()));
357+
session.markSuggestionAsSeen();
358+
337359
// Here we perform "post closing bracket insertion caret correction", which
338360
// consists of the following:
339361
// - Check if the input is a closing bracket
@@ -398,7 +420,7 @@ public void mouseDown(final MouseEvent e) {
398420
int currentOffset = invocationOffset + distanceTraversed;
399421
int lastKnownLine = widget.getLineAtOffset(currentOffset);
400422
qInvocationSessionInstance.transitionToDecisionMade(lastKnownLine + 1);
401-
qInvocationSessionInstance.end();
423+
qInvocationSessionInstance.endImmediately();
402424
return;
403425
}
404426

0 commit comments

Comments
 (0)