blob: b880ccdee8f6d90d806e7066081e11c57b3191c1 [file] [log] [blame]
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
export interface AutocompletionContext {
draftContent: string;
draftContentLength?: number;
commentCompletion: string;
commentCompletionLength?: number;
isFullCommentPrediction?: boolean;
draftInSyncWithSuggestionLength?: number;
modelVersion?: string;
outcome?: number;
requestDurationMs?: number;
commentId?: string;
commentNumber?: number;
filePath?: string;
fileExtension?: string;
similarCharacters?: number;
maxSimilarCharacters?: number;
acceptedSuggestionsCount?: number;
totalAcceptedCharacters?: number;
savedDraftLength?: number;
hasDraftChanged?: boolean;
}
/**
* Caching for autocompleting text, e.g. comments.
*
* If the user continues typing text that matches the completion hint, then keep the hint.
*
* If the user backspaces, then continue using previous hint.
*/
export class AutocompleteCache {
/**
* We are using an ordered list instead of a map here, because we want to evict the oldest
* entries, if the capacity is exceeded. And we want to prefer newer entries over older
* entries, if both match the criteria for being reused.
*/
private cache: AutocompletionContext[] = [];
constructor(private readonly capacity = 10) {}
get(content: string): AutocompletionContext | undefined {
if (content === '') return undefined;
for (let i = this.cache.length - 1; i >= 0; i--) {
const cachedContext = this.cache[i];
const completionContent = cachedContext.draftContent;
const completionHint = cachedContext.commentCompletion;
const completionFull = completionContent + completionHint;
if (completionContent.length > content.length) continue;
if (!completionFull.startsWith(content)) continue;
if (completionFull === content) continue;
const hint = completionFull.substring(content.length);
return {
...cachedContext,
draftContent: content,
commentCompletion: hint,
draftInSyncWithSuggestionLength:
content.length - completionContent.length,
};
}
return undefined;
}
set(context: AutocompletionContext) {
const index = this.cache.findIndex(
c => c.draftContent === context.draftContent
);
if (index !== -1) {
this.cache.splice(index, 1);
} else if (this.cache.length >= this.capacity) {
this.cache.shift();
}
this.cache.push(context);
}
}