Commit 1a4e13dd authored by Mohammed Osumah's avatar Mohammed Osumah 2️⃣ Committed by Tristan Read
Browse files

feat: support code suggestions usage cutoff in vscode

parent b734b074
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
import * as vscode from 'vscode';
import { SUGGESTIONS_API_ERROR } from '@gitlab-org/gitlab-lsp';
import { SUGGESTIONS_API_ERROR, SUGGESTIONS_NO_CREDITS } from '@gitlab-org/gitlab-lsp';
import { GitLabPlatformManager } from '../platform/gitlab_platform';
import { log } from '../log';
import { LanguageServerFeatureStateProvider } from '../language_server/language_server_feature_state_provider';
@@ -52,6 +52,7 @@ export const VisibleCodeSuggestionsState = {
  LOADING: 'code-suggestions-loading',
  UNSUPPORTED_GITLAB_VERSION,
  SUGGESTIONS_API_ERROR,
  SUGGESTIONS_NO_CREDITS,
  AUTHENTICATION_REQUIRED: 'authentication-required',
  SUGGESTIONS_FILE_EXCLUDED: 'code-suggestions-file-excluded',
} as const;
+5 −0
Original line number Diff line number Diff line
@@ -50,6 +50,11 @@ export const CODE_SUGGESTIONS_STATUSES: Record<VisibleCodeSuggestionsState, Stat
      'A GitLab Duo license is required to use this feature. Contact your GitLab administrator to request access.',
    backgroundColor: errorBackgroundColor,
  },
  [VisibleCodeSuggestionsState.SUGGESTIONS_NO_CREDITS]: {
    iconName: 'gitlab-code-suggestions-disabled',
    tooltip:
      'No GitLab Credits remain for this billing period. To continue using Code Suggestions, contact your administrator. When you have more credits, reload the extension.',
  },
  [VisibleCodeSuggestionsState.DISABLED_BY_PROJECT]: {
    iconName: 'gitlab-code-suggestions-disabled',
    tooltip: 'Code suggestions are disabled for this project',
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ export const DUO_CODE_SUGGESTIONS_LANGUAGES = supportedLanguages.map(
  langData => langData.languageId,
);

export const CODE_SUGGESTIONS_NO_CREDIT = 'CODE_SUGGESTIONS_NO_CREDIT';

export const CODE_SUGGESTIONS_MIN_LENGTH = 10;

export const CS_DISABLED_PROJECT_CHECK_INTERVAL = 300000; // 5 min
+41 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ import {
  CODE_SUGGESTIONS,
  UNSUPPORTED_GITLAB_VERSION,
  SUGGESTIONS_DISABLED_BY_USER,
  SUGGESTIONS_NO_CREDITS,
} from '@gitlab-org/gitlab-lsp';
import { createFakePartial } from '../../test_utils/create_fake_partial';
import { createExtensionContext } from '../../test_utils/entities';
@@ -11,8 +12,11 @@ import {
  AllFeaturesState,
  LanguageServerFeatureStateProvider,
} from '../../language_server/language_server_feature_state_provider';
import { UserMessage } from '../../user_message';
import { LanguageServerPolicy, UNSUPPORTED_LANGUAGE } from './language_server_policy';

jest.mock('../../user_message');

describe('LanguageServerPolicy', () => {
  let policy: LanguageServerPolicy;
  let context: vscode.ExtensionContext;
@@ -23,6 +27,7 @@ describe('LanguageServerPolicy', () => {
  });
  let triggerOnChange: (params: AllFeaturesState) => void;
  const engageListener = jest.fn();
  let mockUserMessageTrigger: jest.Mock;

  const engagedPolicyParams = createFakePartial<AllFeaturesState>({
    [CODE_SUGGESTIONS]: {
@@ -86,6 +91,14 @@ describe('LanguageServerPolicy', () => {
  beforeEach(async () => {
    context = createExtensionContext();
    jest.resetAllMocks();

    mockUserMessageTrigger = jest.fn().mockResolvedValue(undefined);
    jest.mocked(UserMessage).mockImplementation(() =>
      createFakePartial<UserMessage>({
        trigger: mockUserMessageTrigger,
      }),
    );

    policy = new LanguageServerPolicy(languageServerFeatureStateProvider, context);
    mockOnChange.mockImplementation(_callback => {
      triggerOnChange = _callback;
@@ -201,5 +214,33 @@ describe('LanguageServerPolicy', () => {
        expect(vscode.window.showWarningMessage).not.toHaveBeenCalled();
      });
    });

    describe(`${SUGGESTIONS_NO_CREDITS}`, () => {
      const noCreditsParams = createFakePartial<AllFeaturesState>({
        [CODE_SUGGESTIONS]: {
          featureId: CODE_SUGGESTIONS,
          engagedChecks: [
            {
              checkId: SUGGESTIONS_NO_CREDITS,
              details: 'No credits remaining',
              engaged: true,
            },
          ],
          allChecks: [
            {
              checkId: SUGGESTIONS_NO_CREDITS,
              details: 'No credits remaining',
              engaged: true,
            },
          ],
        },
      });

      it('triggers the no credits warning message', async () => {
        await triggerOnChange(noCreditsParams);

        expect(mockUserMessageTrigger).toHaveBeenCalled();
      });
    });
  });
});
+20 −0
Original line number Diff line number Diff line
@@ -5,10 +5,13 @@ import {
  UNSUPPORTED_GITLAB_VERSION,
  FeatureStateCheck,
  MINIMUM_CODE_SUGGESTIONS_VERSION,
  SUGGESTIONS_NO_CREDITS,
} 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 { UserMessage } from '../../user_message';
import { CODE_SUGGESTIONS_NO_CREDIT } from '../constants';
import { StatePolicy } from './state_policy';

export const UNSUPPORTED_LANGUAGE = 'code-suggestions-document-unsupported-language';
@@ -28,12 +31,21 @@ export class LanguageServerPolicy implements StatePolicy {

  #instanceUrlsWithShownDeprecatedVersionWarning: Record<string, boolean> = {};

  #noCreditsWarningMessage: UserMessage;

  constructor(
    languageServerFeatureStateProvider: LanguageServerFeatureStateProvider,
    context: vscode.ExtensionContext,
  ) {
    this.#languageServerFeatureStateProvider = languageServerFeatureStateProvider;
    this.#context = context;
    this.#noCreditsWarningMessage = new UserMessage(
      context.globalState,
      CODE_SUGGESTIONS_NO_CREDIT,
      'No GitLab Credits remain for this billing period. To continue using Code Suggestions, contact your administrator. When you have more credits, reload the extension.',
      [],
      'day',
    );
  }

  async init() {
@@ -75,6 +87,10 @@ export class LanguageServerPolicy implements StatePolicy {
    if (stateCheck.checkId === UNSUPPORTED_GITLAB_VERSION && stateCheck.context) {
      await this.#deprecatedVersionHandler(stateCheck.context.baseUrl, stateCheck.context.version);
    }

    if (stateCheck.checkId === SUGGESTIONS_NO_CREDITS) {
      await this.#showNoCreditsWarning();
    }
  }

  // FIXME: Custom messages like these are deprecated in favour of the
@@ -111,4 +127,8 @@ export class LanguageServerPolicy implements StatePolicy {
      });
    }
  }

  async #showNoCreditsWarning() {
    await this.#noCreditsWarningMessage.trigger();
  }
}
Loading