func()

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
}