src/common/code_suggestions/state_policy/language_server_policy.ts (86 lines of code) (raw):

import vscode from 'vscode'; import { CODE_SUGGESTIONS, StateCheckId, UNSUPPORTED_GITLAB_VERSION, FeatureStateCheck, MINIMUM_CODE_SUGGESTIONS_VERSION, } from '@gitlab-org/gitlab-lsp'; import { log } from '../../log'; import { DO_NOT_SHOW_CODE_SUGGESTIONS_VERSION_WARNING } from '../../constants'; import { LanguageServerFeatureStateProvider } from '../../language_server/language_server_feature_state_provider'; import { StatePolicy } from './state_policy'; export const UNSUPPORTED_LANGUAGE = 'code-suggestions-document-unsupported-language'; export class LanguageServerPolicy implements StatePolicy { #subscriptions: vscode.Disposable[] = []; #eventEmitter = new vscode.EventEmitter<boolean>(); #languageServerFeatureStateProvider: LanguageServerFeatureStateProvider; state?: StateCheckId; engaged = false; #context: vscode.ExtensionContext; #instanceUrlsWithShownDeprecatedVersionWarning: Record<string, boolean> = {}; constructor( languageServerFeatureStateProvider: LanguageServerFeatureStateProvider, context: vscode.ExtensionContext, ) { this.#languageServerFeatureStateProvider = languageServerFeatureStateProvider; this.#context = context; } async init() { this.#subscriptions.push( this.#languageServerFeatureStateProvider.onChange(async checkResults => { if (!checkResults) { return; } const checks = checkResults[CODE_SUGGESTIONS]; if (!checks || !checks.allChecks) { return; } const engagedCheck = checks.allChecks?.find(ch => ch.engaged); const newState = engagedCheck?.checkId; const changed = newState !== this.state; this.state = newState; this.engaged = Boolean(newState); if (changed) { this.#eventEmitter.fire(this.engaged); } await this.#handleState(engagedCheck); }), ); } onEngagedChange = this.#eventEmitter.event; dispose(): void { this.#subscriptions.forEach(s => s.dispose()); } async #handleState(stateCheck?: FeatureStateCheck<StateCheckId>) { if (!stateCheck) return; if (stateCheck.checkId === UNSUPPORTED_GITLAB_VERSION && stateCheck.context) { await this.#deprecatedVersionHandler(stateCheck.context.baseUrl, stateCheck.context.version); } } // FIXME: Custom messages like these are deprecated in favour of the // src/common/user_message.ts component async #deprecatedVersionHandler(instanceUrl: string, version: string) { const DO_NOT_SHOW_AGAIN_TEXT = 'Do not show again'; const warningMessage = new vscode.MarkdownString(` GitLab Duo Code Suggestions requires GitLab version ${MINIMUM_CODE_SUGGESTIONS_VERSION} or later. GitLab instance located at: [${instanceUrl}](${instanceUrl}) is currently using ${version}. [Click here](https://docs.gitlab.com/update/) to learn about upgrading. `); log.warn(warningMessage.value); if (instanceUrl in this.#instanceUrlsWithShownDeprecatedVersionWarning) return; const versionWarningRecords = this.#context.globalState.get<Record<string, boolean>>( DO_NOT_SHOW_CODE_SUGGESTIONS_VERSION_WARNING, ); if (versionWarningRecords?.[instanceUrl]) return; this.#instanceUrlsWithShownDeprecatedVersionWarning[instanceUrl] = true; const action = await vscode.window.showWarningMessage( warningMessage.value, DO_NOT_SHOW_AGAIN_TEXT, ); if (action === DO_NOT_SHOW_AGAIN_TEXT) { await this.#context.globalState.update(DO_NOT_SHOW_CODE_SUGGESTIONS_VERSION_WARNING, { ...versionWarningRecords, [instanceUrl]: true, }); } } }