in src/ulsp/controller/scip/scip.go [239:336]
func (c *controller) loadFromDirectories(ctx context.Context, dirs []string) ([]string, error) {
failed := make([]string, 0)
s, err := c.sessions.GetFromContext(ctx)
if err != nil {
return failed, err
}
c.registriesMu.Lock()
reg := c.registries[s.WorkspaceRoot]
if reg == nil {
c.logger.Infof("Initializing registry for %q", s.WorkspaceRoot)
reg = c.createNewScipRegistry(s.WorkspaceRoot, s.Monorepo)
if reg == nil {
c.logger.Warnf("Skipping SCIP loading for %q: failed to initialize registry", s.WorkspaceRoot)
c.registriesMu.Unlock()
return failed, nil
}
c.registries[s.WorkspaceRoot] = reg
}
c.registriesMu.Unlock()
for _, d := range dirs {
fDir := path.Join(s.WorkspaceRoot, d)
scips, err := c.fs.ReadDir(fDir)
if err != nil {
c.logger.Infof("%q is not a valid path for indices", d)
continue
}
var (
wg sync.WaitGroup
mu sync.Mutex
)
scipFiles := make([]struct {
filePath string
loadedSha string
}, 0)
for _, scip := range scips {
if !strings.HasSuffix(scip.Name(), _scipExt) {
continue
}
fPath := path.Join(fDir, scip.Name())
scipFiles = append(scipFiles, struct {
filePath string
loadedSha string
}{
filePath: fPath,
loadedSha: c.loadedIndices[fPath],
})
c.indexNotifier.TrackFile(context.Background(), s.WorkspaceRoot, fPath)
}
// Limit load concurrency to max supported for indexer
sem := make(chan struct{}, reg.LoadConcurrency())
for _, fileData := range scipFiles {
wg.Add(1)
sem <- struct{}{} // Acquire semaphore
go func(fPath string, loadedSha string) {
defer wg.Done()
defer func() { <-sem }() // Release semaphore
c.indexNotifier.NotifyStart(context.Background(), s.WorkspaceRoot, fPath)
sha, err := c.loadScipFile(s.WorkspaceRoot, fPath, loadedSha)
mu.Lock()
var status IndexLoadStatus
if err != nil {
failed = append(failed, fPath)
status = IndexLoadError
} else {
c.loadedIndices[fPath] = sha
status = IndexLoadSuccess
}
mu.Unlock()
c.indexNotifier.NotifyComplete(context.Background(), s.WorkspaceRoot, fPath, status)
}(fileData.filePath, fileData.loadedSha)
}
wg.Wait()
if c.watcher != nil {
err = c.watcher.Add(fDir)
if err != nil {
c.logger.Warnf("Failed to watch for changes in %d: %v", d, err)
}
}
}
if len(failed) > 0 && c.ideGateway != nil {
c.ideGateway.ShowMessage(ctx, &protocol.ShowMessageParams{
Message: fmt.Sprintf("Failed to load %d indices: %v", len(failed), failed),
Type: protocol.MessageTypeInfo,
})
c.logger.Warnf("Failed to load %d indices", len(failed))
}
return failed, nil
}