diff options
Diffstat (limited to 'internal/lsp/watcher')
| -rw-r--r-- | internal/lsp/watcher/watcher.go | 112 |
1 files changed, 56 insertions, 56 deletions
diff --git a/internal/lsp/watcher/watcher.go b/internal/lsp/watcher/watcher.go index 58ad25695..ed8fe6b76 100644 --- a/internal/lsp/watcher/watcher.go +++ b/internal/lsp/watcher/watcher.go @@ -13,9 +13,9 @@ import ( "github.com/bmatcuk/doublestar/v4" "github.com/fsnotify/fsnotify" "github.com/opencode-ai/opencode/internal/config" - "github.com/opencode-ai/opencode/internal/logging" "github.com/opencode-ai/opencode/internal/lsp" "github.com/opencode-ai/opencode/internal/lsp/protocol" + "log/slog" ) // WorkspaceWatcher manages LSP file watching @@ -46,7 +46,7 @@ func NewWorkspaceWatcher(client *lsp.Client) *WorkspaceWatcher { func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watchers []protocol.FileSystemWatcher) { cnf := config.Get() - logging.Debug("Adding file watcher registrations") + slog.Debug("Adding file watcher registrations") w.registrationMu.Lock() defer w.registrationMu.Unlock() @@ -55,33 +55,33 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc // Print detailed registration information for debugging if cnf.DebugLSP { - logging.Debug("Adding file watcher registrations", + slog.Debug("Adding file watcher registrations", "id", id, "watchers", len(watchers), "total", len(w.registrations), ) for i, watcher := range watchers { - logging.Debug("Registration", "index", i+1) + slog.Debug("Registration", "index", i+1) // Log the GlobPattern switch v := watcher.GlobPattern.Value.(type) { case string: - logging.Debug("GlobPattern", "pattern", v) + slog.Debug("GlobPattern", "pattern", v) case protocol.RelativePattern: - logging.Debug("GlobPattern", "pattern", v.Pattern) + slog.Debug("GlobPattern", "pattern", v.Pattern) // Log BaseURI details switch u := v.BaseURI.Value.(type) { case string: - logging.Debug("BaseURI", "baseURI", u) + slog.Debug("BaseURI", "baseURI", u) case protocol.DocumentUri: - logging.Debug("BaseURI", "baseURI", u) + slog.Debug("BaseURI", "baseURI", u) default: - logging.Debug("BaseURI", "baseURI", u) + slog.Debug("BaseURI", "baseURI", u) } default: - logging.Debug("GlobPattern", "unknown type", fmt.Sprintf("%T", v)) + slog.Debug("GlobPattern", "unknown type", fmt.Sprintf("%T", v)) } // Log WatchKind @@ -90,13 +90,13 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc watchKind = *watcher.Kind } - logging.Debug("WatchKind", "kind", watchKind) + slog.Debug("WatchKind", "kind", watchKind) } } // Determine server type for specialized handling serverName := getServerNameFromContext(ctx) - logging.Debug("Server type detected", "serverName", serverName) + slog.Debug("Server type detected", "serverName", serverName) // Check if this server has sent file watchers hasFileWatchers := len(watchers) > 0 @@ -124,7 +124,7 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc filesOpened += highPriorityFilesOpened if cnf.DebugLSP { - logging.Debug("Opened high-priority files", + slog.Debug("Opened high-priority files", "count", highPriorityFilesOpened, "serverName", serverName) } @@ -132,7 +132,7 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc // If we've already opened enough high-priority files, we might not need more if filesOpened >= maxFilesToOpen { if cnf.DebugLSP { - logging.Debug("Reached file limit with high-priority files", + slog.Debug("Reached file limit with high-priority files", "filesOpened", filesOpened, "maxFiles", maxFilesToOpen) } @@ -150,7 +150,7 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc if d.IsDir() { if path != w.workspacePath && shouldExcludeDir(path) { if cnf.DebugLSP { - logging.Debug("Skipping excluded directory", "path", path) + slog.Debug("Skipping excluded directory", "path", path) } return filepath.SkipDir } @@ -178,7 +178,7 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc elapsedTime := time.Since(startTime) if cnf.DebugLSP { - logging.Debug("Limited workspace scan complete", + slog.Debug("Limited workspace scan complete", "filesOpened", filesOpened, "maxFiles", maxFilesToOpen, "elapsedTime", elapsedTime.Seconds(), @@ -187,11 +187,11 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc } if err != nil && cnf.DebugLSP { - logging.Debug("Error scanning workspace for files to open", "error", err) + slog.Debug("Error scanning workspace for files to open", "error", err) } }() } else if cnf.DebugLSP { - logging.Debug("Using on-demand file loading for server", "server", serverName) + slog.Debug("Using on-demand file loading for server", "server", serverName) } } @@ -264,7 +264,7 @@ func (w *WorkspaceWatcher) openHighPriorityFiles(ctx context.Context, serverName matches, err := doublestar.Glob(os.DirFS(w.workspacePath), pattern) if err != nil { if cnf.DebugLSP { - logging.Debug("Error finding high-priority files", "pattern", pattern, "error", err) + slog.Debug("Error finding high-priority files", "pattern", pattern, "error", err) } continue } @@ -282,12 +282,12 @@ func (w *WorkspaceWatcher) openHighPriorityFiles(ctx context.Context, serverName // Open the file if err := w.client.OpenFile(ctx, fullPath); err != nil { if cnf.DebugLSP { - logging.Debug("Error opening high-priority file", "path", fullPath, "error", err) + slog.Debug("Error opening high-priority file", "path", fullPath, "error", err) } } else { filesOpened++ if cnf.DebugLSP { - logging.Debug("Opened high-priority file", "path", fullPath) + slog.Debug("Opened high-priority file", "path", fullPath) } } @@ -319,7 +319,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str } serverName := getServerNameFromContext(ctx) - logging.Debug("Starting workspace watcher", "workspacePath", workspacePath, "serverName", serverName) + slog.Debug("Starting workspace watcher", "workspacePath", workspacePath, "serverName", serverName) // Register handler for file watcher registrations from the server lsp.RegisterFileWatchHandler(func(id string, watchers []protocol.FileSystemWatcher) { @@ -328,7 +328,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str watcher, err := fsnotify.NewWatcher() if err != nil { - logging.Error("Error creating watcher", "error", err) + slog.Error("Error creating watcher", "error", err) } defer watcher.Close() @@ -342,7 +342,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str if d.IsDir() && path != workspacePath { if shouldExcludeDir(path) { if cnf.DebugLSP { - logging.Debug("Skipping excluded directory", "path", path) + slog.Debug("Skipping excluded directory", "path", path) } return filepath.SkipDir } @@ -352,14 +352,14 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str if d.IsDir() { err = watcher.Add(path) if err != nil { - logging.Error("Error watching path", "path", path, "error", err) + slog.Error("Error watching path", "path", path, "error", err) } } return nil }) if err != nil { - logging.Error("Error walking workspace", "error", err) + slog.Error("Error walking workspace", "error", err) } // Event loop @@ -381,18 +381,18 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str if err != nil { if os.IsNotExist(err) { // File was deleted between event and processing - ignore - logging.Debug("File deleted between create event and stat", "path", event.Name) + slog.Debug("File deleted between create event and stat", "path", event.Name) continue } - logging.Error("Error getting file info", "path", event.Name, "error", err) + slog.Error("Error getting file info", "path", event.Name, "error", err) continue } - + if info.IsDir() { // Skip excluded directories if !shouldExcludeDir(event.Name) { if err := watcher.Add(event.Name); err != nil { - logging.Error("Error adding directory to watcher", "path", event.Name, "error", err) + slog.Error("Error adding directory to watcher", "path", event.Name, "error", err) } } } else { @@ -406,7 +406,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str // Debug logging if cnf.DebugLSP { matched, kind := w.isPathWatched(event.Name) - logging.Debug("File event", + slog.Debug("File event", "path", event.Name, "operation", event.Op.String(), "watched", matched, @@ -427,7 +427,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str // Just send the notification if needed info, err := os.Stat(event.Name) if err != nil { - logging.Error("Error getting file info", "path", event.Name, "error", err) + slog.Error("Error getting file info", "path", event.Name, "error", err) return } if !info.IsDir() && watchKind&protocol.WatchCreate != 0 { @@ -455,7 +455,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str if !ok { return } - logging.Error("Error watching file", "error", err) + slog.Error("Error watching file", "error", err) } } } @@ -580,7 +580,7 @@ func matchesSimpleGlob(pattern, path string) bool { // Fall back to simple matching for simpler patterns matched, err := filepath.Match(pattern, path) if err != nil { - logging.Error("Error matching pattern", "pattern", pattern, "path", path, "error", err) + slog.Error("Error matching pattern", "pattern", pattern, "path", path, "error", err) return false } @@ -591,7 +591,7 @@ func matchesSimpleGlob(pattern, path string) bool { func (w *WorkspaceWatcher) matchesPattern(path string, pattern protocol.GlobPattern) bool { patternInfo, err := pattern.AsPattern() if err != nil { - logging.Error("Error parsing pattern", "pattern", pattern, "error", err) + slog.Error("Error parsing pattern", "pattern", pattern, "error", err) return false } @@ -616,7 +616,7 @@ func (w *WorkspaceWatcher) matchesPattern(path string, pattern protocol.GlobPatt // Make path relative to basePath for matching relPath, err := filepath.Rel(basePath, path) if err != nil { - logging.Error("Error getting relative path", "path", path, "basePath", basePath, "error", err) + slog.Error("Error getting relative path", "path", path, "basePath", basePath, "error", err) return false } relPath = filepath.ToSlash(relPath) @@ -654,15 +654,15 @@ func (w *WorkspaceWatcher) debounceHandleFileEvent(ctx context.Context, uri stri func (w *WorkspaceWatcher) handleFileEvent(ctx context.Context, uri string, changeType protocol.FileChangeType) { // If the file is open and it's a change event, use didChange notification filePath := uri[7:] // Remove "file://" prefix - + if changeType == protocol.FileChangeType(protocol.Deleted) { // Always clear diagnostics for deleted files w.client.ClearDiagnosticsForURI(protocol.DocumentUri(uri)) - + // If the file was open, close it in the LSP client if w.client.IsFileOpen(filePath) { if err := w.client.CloseFile(ctx, filePath); err != nil { - logging.Debug("Error closing deleted file in LSP client", "file", filePath, "error", err) + slog.Debug("Error closing deleted file in LSP client", "file", filePath, "error", err) // Continue anyway - the file is gone } } @@ -671,19 +671,19 @@ func (w *WorkspaceWatcher) handleFileEvent(ctx context.Context, uri string, chan if _, err := os.Stat(filePath); err != nil { if os.IsNotExist(err) { // File was deleted between the event and now - treat as delete - logging.Debug("File deleted between change event and processing", "file", filePath) + slog.Debug("File deleted between change event and processing", "file", filePath) w.handleFileEvent(ctx, uri, protocol.FileChangeType(protocol.Deleted)) return } - logging.Error("Error getting file info", "path", filePath, "error", err) + slog.Error("Error getting file info", "path", filePath, "error", err) return } - + // File exists and is open, notify change if w.client.IsFileOpen(filePath) { err := w.client.NotifyChange(ctx, filePath) if err != nil { - logging.Error("Error notifying change", "error", err) + slog.Error("Error notifying change", "error", err) } return } @@ -692,17 +692,17 @@ func (w *WorkspaceWatcher) handleFileEvent(ctx context.Context, uri string, chan if _, err := os.Stat(filePath); err != nil { if os.IsNotExist(err) { // File was deleted between the event and now - ignore - logging.Debug("File deleted between create event and processing", "file", filePath) + slog.Debug("File deleted between create event and processing", "file", filePath) return } - logging.Error("Error getting file info", "path", filePath, "error", err) + slog.Error("Error getting file info", "path", filePath, "error", err) return } } // Notify LSP server about the file event using didChangeWatchedFiles if err := w.notifyFileEvent(ctx, uri, changeType); err != nil { - logging.Error("Error notifying LSP server about file event", "error", err) + slog.Error("Error notifying LSP server about file event", "error", err) } } @@ -710,7 +710,7 @@ func (w *WorkspaceWatcher) handleFileEvent(ctx context.Context, uri string, chan func (w *WorkspaceWatcher) notifyFileEvent(ctx context.Context, uri string, changeType protocol.FileChangeType) error { cnf := config.Get() if cnf.DebugLSP { - logging.Debug("Notifying file event", + slog.Debug("Notifying file event", "uri", uri, "changeType", changeType, ) @@ -874,7 +874,7 @@ func shouldExcludeFile(filePath string) bool { if strings.HasSuffix(filePath, "~") { return true } - + // Skip numeric temporary files (often created by editors) if _, err := strconv.Atoi(fileName); err == nil { return true @@ -890,7 +890,7 @@ func shouldExcludeFile(filePath string) bool { // Skip large files if info.Size() > maxFileSize { if cnf.DebugLSP { - logging.Debug("Skipping large file", + slog.Debug("Skipping large file", "path", filePath, "size", info.Size(), "maxSize", maxFileSize, @@ -913,13 +913,13 @@ func (w *WorkspaceWatcher) openMatchingFile(ctx context.Context, path string) { if err != nil { if os.IsNotExist(err) { // File was deleted between event and processing - ignore - logging.Debug("File deleted between event and openMatchingFile", "path", path) + slog.Debug("File deleted between event and openMatchingFile", "path", path) return } - logging.Error("Error getting file info", "path", path, "error", err) + slog.Error("Error getting file info", "path", path, "error", err) return } - + if info.IsDir() { return } @@ -938,10 +938,10 @@ func (w *WorkspaceWatcher) openMatchingFile(ctx context.Context, path string) { // This helps with project initialization for certain language servers if isHighPriorityFile(path, serverName) { if cnf.DebugLSP { - logging.Debug("Opening high-priority file", "path", path, "serverName", serverName) + slog.Debug("Opening high-priority file", "path", path, "serverName", serverName) } if err := w.client.OpenFile(ctx, path); err != nil && cnf.DebugLSP { - logging.Error("Error opening high-priority file", "path", path, "error", err) + slog.Error("Error opening high-priority file", "path", path, "error", err) } return } @@ -953,7 +953,7 @@ func (w *WorkspaceWatcher) openMatchingFile(ctx context.Context, path string) { // Check file size - for preloading we're more conservative if info.Size() > (1 * 1024 * 1024) { // 1MB limit for preloaded files if cnf.DebugLSP { - logging.Debug("Skipping large file for preloading", "path", path, "size", info.Size()) + slog.Debug("Skipping large file for preloading", "path", path, "size", info.Size()) } return } @@ -985,7 +985,7 @@ func (w *WorkspaceWatcher) openMatchingFile(ctx context.Context, path string) { if shouldOpen { // Don't need to check if it's already open - the client.OpenFile handles that if err := w.client.OpenFile(ctx, path); err != nil && cnf.DebugLSP { - logging.Error("Error opening file", "path", path, "error", err) + slog.Error("Error opening file", "path", path, "error", err) } } } |
