summaryrefslogtreecommitdiff
path: root/internal/lsp/completion_service.go
blob: 5bfa13108f06c4fc6d01875628ce77015e7507ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package lsp

import (
	"context"
)

// completionService owns the entire code-completion subsystem that used to be
// scattered across Server. It bundles the completion cache/throttle state
// (completionState) with the request-handling logic, and reaches back into the
// Server (via srv) for shared infrastructure such as configuration, LLM
// clients, document access and stats counters.
//
// Splitting this out of Server keeps the completion logic cohesive and lets the
// completionState mutex stay private to this subsystem, independent of
// Server.mu (the two locks are never held simultaneously).
type completionService struct {
	srv *Server
	completionState
}

// newCompletionService constructs the completion subsystem bound to srv.
func newCompletionService(srv *Server) *completionService {
	return &completionService{
		srv:             srv,
		completionState: newCompletionState(),
	}
}

// waitForThrottle gates completion (and chat) LLM calls using the configured
// throttle interval. It lives here because the throttle clock is part of the
// completion state.
func (cs *completionService) waitForThrottle(ctx context.Context) bool {
	return cs.completionState.waitForThrottle(ctx, cs.srv.completionThrottle())
}

// completionSvc returns the completion subsystem, lazily constructing it for
// the bare Server literals used in some tests. Production code always has it
// wired up by NewServer.
func (s *Server) completionSvc() *completionService {
	if s.completion == nil {
		s.completion = newCompletionService(s)
	}
	return s.completion
}

// --- Server delegation shims ---------------------------------------------
// These keep existing Server call sites (and tests) working while the real
// state and behavior live on completionService.

func (s *Server) storePendingCompletion(key string, items []CompletionItem) {
	s.completionSvc().storePendingCompletion(key, items)
}

func (s *Server) setCompletionsDisabled(disabled bool) bool {
	return s.completionSvc().setCompletionsDisabled(disabled)
}

func (s *Server) completionDisabled() bool {
	return s.completionSvc().completionDisabled()
}

func (s *Server) takePendingCompletion(key string) []CompletionItem {
	return s.completionSvc().takePendingCompletion(key)
}

func (s *Server) completionCacheGet(key string) (string, bool) {
	return s.completionSvc().cacheGet(key)
}

func (s *Server) completionCachePut(key, value string) {
	s.completionSvc().cachePut(key, value)
}

func (s *Server) waitForThrottle(ctx context.Context) bool {
	return s.completionSvc().waitForThrottle(ctx)
}