Commit 80651b2c authored by Tomas Vik (OOO back on 2026-08-31)'s avatar Tomas Vik (OOO back on 2026-08-31) 🌴
Browse files

feat: show loading state for LS suggestions

parent ec2cbc3c
Loading
Loading
Loading
Loading
+48 −26
Original line number Diff line number Diff line
@@ -11,10 +11,10 @@ describe('LanguageClientMiddleware', () => {
  });

  describe('provideInlineCompletionItem', () => {
    const document = createFakePartial<vscode.TextDocument>({});
    const position = createFakePartial<vscode.Position>({});
    const context = createFakePartial<vscode.InlineCompletionContext>({});
    const token = createFakePartial<vscode.CancellationToken>({});
    const d = createFakePartial<vscode.TextDocument>({});
    const p = createFakePartial<vscode.Position>({});
    const ctx = createFakePartial<vscode.InlineCompletionContext>({});
    const tkn = createFakePartial<vscode.CancellationToken>({});

    it('returns empty array if suggestions are in a disabled state', async () => {
      const stateManager = createFakePartial<CodeSuggestionsStateManager>({
@@ -23,35 +23,57 @@ describe('LanguageClientMiddleware', () => {
      const middleware = new LanguageClientMiddleware(stateManager);
      const next = jest.fn();

      const result = await middleware.provideInlineCompletionItems(
        document,
        position,
        context,
        token,
        next,
      );
      const result = await middleware.provideInlineCompletionItems(d, p, ctx, tkn, next);

      expect(result).toEqual([]);
      expect(next).not.toHaveBeenCalled();
    });

    it('calls through to default logic if suggestions are enabled', async () => {
      const stateManager = createFakePartial<CodeSuggestionsStateManager>({
    describe('when suggestions enabled', () => {
      let stateManager: CodeSuggestionsStateManager;
      let middleware: LanguageClientMiddleware;

      let setLoading: jest.Func;

      beforeEach(() => {
        setLoading = jest.fn();
        stateManager = createFakePartial<CodeSuggestionsStateManager>({
          isDisabledByUser: () => false,
          setLoading,
        });
        middleware = new LanguageClientMiddleware(stateManager);
      });

      it('calls through to default logic if suggestions are enabled', async () => {
        const mockItem = createFakePartial<vscode.InlineCompletionItem>({});
        const next = jest.fn().mockResolvedValue([mockItem]);

        const result = await middleware.provideInlineCompletionItems(d, p, ctx, tkn, next);

        expect(result).toEqual([mockItem]);
      });

      it('sets suggestions to loading state', async () => {
        const next = jest.fn().mockResolvedValue([]);

        await middleware.provideInlineCompletionItems(d, p, ctx, tkn, next);

        expect(setLoading).toHaveBeenCalledTimes(2);
        expect(setLoading).toHaveBeenCalledWith(true);
        expect(setLoading).toHaveBeenLastCalledWith(false);
      });

      it('sets loading to false even if fetching suggestions throws an error', async () => {
        const next = jest.fn().mockRejectedValue(new Error());

        await expect(
          middleware.provideInlineCompletionItems(d, p, ctx, tkn, next),
        ).rejects.toThrow();

        expect(setLoading).toHaveBeenCalledTimes(2);
        expect(setLoading).toHaveBeenCalledWith(true);
        expect(setLoading).toHaveBeenLastCalledWith(false);
      });
      const middleware = new LanguageClientMiddleware(stateManager);
      const item = createFakePartial<vscode.InlineCompletionItem>({});
      const next = jest.fn().mockResolvedValue([item]);

      const result = await middleware.provideInlineCompletionItems(
        document,
        position,
        context,
        token,
        next,
      );

      expect(result).toEqual([item]);
    });
  });
});
+7 −1
Original line number Diff line number Diff line
@@ -27,6 +27,12 @@ export class LanguageClientMiddleware implements InlineCompletionMiddleware, Com
    if (this.#stateManager.isDisabledByUser()) {
      return [];
    }
    return next(document, position, context, token);

    this.#stateManager.setLoading(true);
    try {
      return await next(document, position, context, token);
    } finally {
      this.#stateManager.setLoading(false);
    }
  }
}