in plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInlineInputListener.java [265:384]
public void documentChanged(final DocumentEvent event) {
QInvocationSession session = QInvocationSession.getInstance();
if (session == null || !session.isPreviewingSuggestions()) {
return;
}
String input = event.getText();
if (input.equals("( ") || input.equals("[ ") || input.equals("< ") || input.equals("\" ")
|| input.equals("\' ")) {
input = input.substring(0, 1);
}
String currentSuggestion = session.getCurrentSuggestion().getInsertText();
int currentOffset = widget.getCaretOffset();
if (input.isEmpty()) {
if (distanceTraversed <= 0) {
// discard all suggestions as caret position is less than request invocation position
session.updateCompletionStates(new ArrayList<String>());
session.transitionToDecisionMade();
session.end();
return;
}
distanceTraversed = typeaheadProcessor.getNewDistanceTraversedOnDeleteAndUpdateBracketState(
event.getLength(), distanceTraversed, brackets);
if (distanceTraversed < 0) {
// discard all suggestions as caret position is less than request invocation position
session.updateCompletionStates(new ArrayList<String>());
session.transitionToDecisionMade();
session.end();
}
// note: distanceTraversed as 0 is currently understood to be when a user presses BS removing any typeahead
if (distanceTraversed == 0) {
// reset completion states for all suggestions when user reverts to request
// invocation state
session.resetCompletionStates();
// mark currently displayed suggestion as seen
session.markSuggestionAsSeen();
}
return;
}
// Here we perform "pre-open bracket insertion input sanitation", which consists
// of the following:
// - Checks to see if the input contains anything inserted on behalf of user by
// eclipse (i.e. auto closing bracket).
// - If it does, get rid of that portion (note that at this point the document
// has already been changed so we are really deleting the extra portion and
// replacing it with what should remain).
// - Lastly, we would want to return early for these two cases. This is because
// the very act of altering the document will trigger this callback once again
// so there is no need to validate the input this time around.
TypeaheadProcessorInstruction preprocessInstruction = typeaheadProcessor
.preprocessDocumentChangedBuffer(distanceTraversed, currentOffset, input, brackets);
if (preprocessInstruction.shouldModifyCaretOffset()) {
widget.setCaretOffset(preprocessInstruction.getCaretOffset());
}
if (preprocessInstruction.shouldModifyDocument()) {
try {
int expandedOffset = QEclipseEditorUtils.getOffsetInFullyExpandedDocument(session.getViewer(),
preprocessInstruction.getDocInsertOffset());
event.getDocument().replace(expandedOffset, preprocessInstruction.getDocInsertLength(),
preprocessInstruction.getDocInsertContent());
return;
} catch (BadLocationException e) {
Activator.getLogger().error("Error performing open bracket sanitation during typeahead", e);
}
}
boolean isOutOfBounds = distanceTraversed + input.length() >= currentSuggestion.length()
|| distanceTraversed < 0;
if (isOutOfBounds || !isInputAMatch(currentSuggestion, distanceTraversed, input)) {
distanceTraversed += input.length();
event.getDocument().removeDocumentListener(this);
StyledText widget = session.getViewer().getTextWidget();
int caretLine = widget.getLineAtOffset(widget.getCaretOffset());
int linesOfInput = input.split(widget.getLineDelimiter()).length;
int lineToUnsetIndent = caretLine + linesOfInput;
session.transitionToDecisionMade(lineToUnsetIndent);
Display.getCurrent().asyncExec(() -> {
if (session.isActive()) {
// discard suggestions and end immediately as typeahead does not match
session.updateCompletionStates(new ArrayList<String>());
session.endImmediately();
}
});
return;
}
// discard all other suggestions except for current one as typeahead matches it
// also mark current one as seen as it continues to be displayed
session.updateCompletionStates(List.of(session.getCurrentSuggestion().getItemId()));
session.markSuggestionAsSeen();
// Here we perform "post closing bracket insertion caret correction", which
// consists of the following:
// - Check if the input is a closing bracket
// - If it is, check to see if it corresponds to the most recent unresolved open
// bracket
// - If it is, we would need to increment the current caret offset, this is
// because the closing bracket would have been inserted by verifyKey and not
// organically, which does not advance the caret.
TypeaheadProcessorInstruction postProcessInstruction = typeaheadProcessor
.postProcessDocumentChangeBuffer(distanceTraversed, currentOffset, input, brackets);
if (postProcessInstruction.shouldModifyCaretOffset()) {
int targetOffset = postProcessInstruction.getCaretOffset();
widget.setCaretOffset(targetOffset);
}
for (int i = distanceTraversed; i < distanceTraversed + input.length(); i++) {
var bracket = brackets[i];
if (bracket != null) {
bracket.onTypeOver();
}
}
distanceTraversed += input.length();
}