diff options
| author | Kujtim Hoxha <[email protected]> | 2025-04-09 19:07:39 +0200 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-04-09 19:07:39 +0200 |
| commit | d39d52d95d6aaab67fb3a17efb9ed62cc290e72f (patch) | |
| tree | 940bad6f0c847ceb213e5fc684b6d87cbf9d6996 /internal/lsp | |
| parent | 0d8d324ac6e640b95f4f2f62fd189399a959319a (diff) | |
| download | opencode-d39d52d95d6aaab67fb3a17efb9ed62cc290e72f.tar.gz opencode-d39d52d95d6aaab67fb3a17efb9ed62cc290e72f.zip | |
finish logs page
Diffstat (limited to 'internal/lsp')
| -rw-r--r-- | internal/lsp/client.go | 20 | ||||
| -rw-r--r-- | internal/lsp/handlers.go | 17 | ||||
| -rw-r--r-- | internal/lsp/transport.go | 70 | ||||
| -rw-r--r-- | internal/lsp/watcher/watcher.go | 118 |
4 files changed, 131 insertions, 94 deletions
diff --git a/internal/lsp/client.go b/internal/lsp/client.go index ddf28ca2a..1b1456614 100644 --- a/internal/lsp/client.go +++ b/internal/lsp/client.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "io" - "log" "os" "os/exec" "strings" @@ -14,9 +13,13 @@ import ( "sync/atomic" "time" + "github.com/kujtimiihoxha/termai/internal/config" + "github.com/kujtimiihoxha/termai/internal/logging" "github.com/kujtimiihoxha/termai/internal/lsp/protocol" ) +var logger = logging.Get() + type Client struct { Cmd *exec.Cmd stdin io.WriteCloser @@ -357,6 +360,7 @@ func (c *Client) NotifyChange(ctx context.Context, filepath string) error { } func (c *Client) CloseFile(ctx context.Context, filepath string) error { + cnf := config.Get() uri := fmt.Sprintf("file://%s", filepath) c.openFilesMu.Lock() @@ -371,7 +375,10 @@ func (c *Client) CloseFile(ctx context.Context, filepath string) error { URI: protocol.DocumentUri(uri), }, } - log.Println("Closing", params.TextDocument.URI.Dir()) + + if cnf.Debug { + logger.Debug("Closing file", "file", filepath) + } if err := c.Notify(ctx, "textDocument/didClose", params); err != nil { return err } @@ -393,6 +400,7 @@ func (c *Client) IsFileOpen(filepath string) bool { // CloseAllFiles closes all currently open files func (c *Client) CloseAllFiles(ctx context.Context) { + cnf := config.Get() c.openFilesMu.Lock() filesToClose := make([]string, 0, len(c.openFiles)) @@ -407,13 +415,13 @@ func (c *Client) CloseAllFiles(ctx context.Context) { // Then close them all for _, filePath := range filesToClose { err := c.CloseFile(ctx, filePath) - if err != nil && debug { - log.Printf("Error closing file %s: %v", filePath, err) + if err != nil && cnf.Debug { + logger.Warn("Error closing file", "file", filePath, "error", err) } } - if debug { - log.Printf("Closed %d files", len(filesToClose)) + if cnf.Debug { + logger.Debug("Closed all files", "files", filesToClose) } } diff --git a/internal/lsp/handlers.go b/internal/lsp/handlers.go index f26a5a6ba..5fb9b49a5 100644 --- a/internal/lsp/handlers.go +++ b/internal/lsp/handlers.go @@ -2,8 +2,8 @@ package lsp import ( "encoding/json" - "log" + "github.com/kujtimiihoxha/termai/internal/config" "github.com/kujtimiihoxha/termai/internal/lsp/protocol" "github.com/kujtimiihoxha/termai/internal/lsp/util" ) @@ -17,7 +17,7 @@ func HandleWorkspaceConfiguration(params json.RawMessage) (any, error) { func HandleRegisterCapability(params json.RawMessage) (any, error) { var registerParams protocol.RegistrationParams if err := json.Unmarshal(params, ®isterParams); err != nil { - log.Printf("Error unmarshaling registration params: %v", err) + logger.Error("Error unmarshaling registration params", "error", err) return nil, err } @@ -27,13 +27,13 @@ func HandleRegisterCapability(params json.RawMessage) (any, error) { // Parse the registration options optionsJSON, err := json.Marshal(reg.RegisterOptions) if err != nil { - log.Printf("Error marshaling registration options: %v", err) + logger.Error("Error marshaling registration options", "error", err) continue } var options protocol.DidChangeWatchedFilesRegistrationOptions if err := json.Unmarshal(optionsJSON, &options); err != nil { - log.Printf("Error unmarshaling registration options: %v", err) + logger.Error("Error unmarshaling registration options", "error", err) continue } @@ -53,7 +53,7 @@ func HandleApplyEdit(params json.RawMessage) (any, error) { err := util.ApplyWorkspaceEdit(edit.Edit) if err != nil { - log.Printf("Error applying workspace edit: %v", err) + logger.Error("Error applying workspace edit", "error", err) return protocol.ApplyWorkspaceEditResult{Applied: false, FailureReason: err.Error()}, nil } @@ -81,19 +81,22 @@ func notifyFileWatchRegistration(id string, watchers []protocol.FileSystemWatche // Notifications func HandleServerMessage(params json.RawMessage) { + cnf := config.Get() var msg struct { Type int `json:"type"` Message string `json:"message"` } if err := json.Unmarshal(params, &msg); err == nil { - log.Printf("Server message: %s\n", msg.Message) + if cnf.Debug { + logger.Debug("Server message", "type", msg.Type, "message", msg.Message) + } } } func HandleDiagnostics(client *Client, params json.RawMessage) { var diagParams protocol.PublishDiagnosticsParams if err := json.Unmarshal(params, &diagParams); err != nil { - log.Printf("Error unmarshaling diagnostic params: %v", err) + logger.Error("Error unmarshaling diagnostics params", "error", err) return } diff --git a/internal/lsp/transport.go b/internal/lsp/transport.go index 120aef3e4..93253f4d6 100644 --- a/internal/lsp/transport.go +++ b/internal/lsp/transport.go @@ -6,12 +6,10 @@ import ( "encoding/json" "fmt" "io" - "log" - "os" "strings" -) -var debug = os.Getenv("DEBUG") != "" + "github.com/kujtimiihoxha/termai/internal/config" +) // Write writes an LSP message to the given writer func WriteMessage(w io.Writer, msg *Message) error { @@ -19,10 +17,10 @@ func WriteMessage(w io.Writer, msg *Message) error { if err != nil { return fmt.Errorf("failed to marshal message: %w", err) } + cnf := config.Get() - if debug { - log.Printf("%v", msg.Method) - log.Printf("-> Sending: %s", string(data)) + if cnf.Debug { + logger.Debug("Sending message to server", "method", msg.Method, "id", msg.ID) } _, err = fmt.Fprintf(w, "Content-Length: %d\r\n\r\n", len(data)) @@ -40,6 +38,7 @@ func WriteMessage(w io.Writer, msg *Message) error { // ReadMessage reads a single LSP message from the given reader func ReadMessage(r *bufio.Reader) (*Message, error) { + cnf := config.Get() // Read headers var contentLength int for { @@ -49,8 +48,8 @@ func ReadMessage(r *bufio.Reader) (*Message, error) { } line = strings.TrimSpace(line) - if debug { - log.Printf("<- Header: %s", line) + if cnf.Debug { + logger.Debug("Received header", "line", line) } if line == "" { @@ -65,8 +64,8 @@ func ReadMessage(r *bufio.Reader) (*Message, error) { } } - if debug { - log.Printf("<- Reading content with length: %d", contentLength) + if cnf.Debug { + logger.Debug("Content-Length", "length", contentLength) } // Read content @@ -76,8 +75,8 @@ func ReadMessage(r *bufio.Reader) (*Message, error) { return nil, fmt.Errorf("failed to read content: %w", err) } - if debug { - log.Printf("<- Received: %s", string(content)) + if cnf.Debug { + logger.Debug("Received content", "content", string(content)) } // Parse message @@ -91,19 +90,20 @@ func ReadMessage(r *bufio.Reader) (*Message, error) { // handleMessages reads and dispatches messages in a loop func (c *Client) handleMessages() { + cnf := config.Get() for { msg, err := ReadMessage(c.stdout) if err != nil { - if debug { - log.Printf("Error reading message: %v", err) + if cnf.Debug { + logger.Error("Error reading message", "error", err) } return } // Handle server->client request (has both Method and ID) if msg.Method != "" && msg.ID != 0 { - if debug { - log.Printf("Received request from server: method=%s id=%d", msg.Method, msg.ID) + if cnf.Debug { + logger.Debug("Received request from server", "method", msg.Method, "id", msg.ID) } response := &Message{ @@ -143,7 +143,7 @@ func (c *Client) handleMessages() { // Send response back to server if err := WriteMessage(c.stdin, response); err != nil { - log.Printf("Error sending response to server: %v", err) + logger.Error("Error sending response to server", "error", err) } continue @@ -156,12 +156,12 @@ func (c *Client) handleMessages() { c.notificationMu.RUnlock() if ok { - if debug { - log.Printf("Handling notification: %s", msg.Method) + if cnf.Debug { + logger.Debug("Handling notification", "method", msg.Method) } go handler(msg.Params) - } else if debug { - log.Printf("No handler for notification: %s", msg.Method) + } else if cnf.Debug { + logger.Debug("No handler for notification", "method", msg.Method) } continue } @@ -173,13 +173,13 @@ func (c *Client) handleMessages() { c.handlersMu.RUnlock() if ok { - if debug { - log.Printf("Sending response for ID %d to handler", msg.ID) + if cnf.Debug { + logger.Debug("Received response for request", "id", msg.ID) } ch <- msg close(ch) - } else if debug { - log.Printf("No handler for response ID: %d", msg.ID) + } else if cnf.Debug { + logger.Debug("No handler for response", "id", msg.ID) } } } @@ -187,10 +187,11 @@ func (c *Client) handleMessages() { // Call makes a request and waits for the response func (c *Client) Call(ctx context.Context, method string, params any, result any) error { + cnf := config.Get() id := c.nextID.Add(1) - if debug { - log.Printf("Making call: method=%s id=%d", method, id) + if cnf.Debug { + logger.Debug("Making call", "method", method, "id", id) } msg, err := NewRequest(id, method, params) @@ -215,15 +216,15 @@ func (c *Client) Call(ctx context.Context, method string, params any, result any return fmt.Errorf("failed to send request: %w", err) } - if debug { - log.Printf("Waiting for response to request ID: %d", id) + if cnf.Debug { + logger.Debug("Request sent", "method", method, "id", id) } // Wait for response resp := <-ch - if debug { - log.Printf("Received response for request ID: %d", id) + if cnf.Debug { + logger.Debug("Received response", "id", id) } if resp.Error != nil { @@ -247,8 +248,9 @@ func (c *Client) Call(ctx context.Context, method string, params any, result any // Notify sends a notification (a request without an ID that doesn't expect a response) func (c *Client) Notify(ctx context.Context, method string, params any) error { - if debug { - log.Printf("Sending notification: method=%s", method) + cnf := config.Get() + if cnf.Debug { + logger.Debug("Sending notification", "method", method) } msg, err := NewNotification(method, params) diff --git a/internal/lsp/watcher/watcher.go b/internal/lsp/watcher/watcher.go index 7a6eaacc5..cfd389ed1 100644 --- a/internal/lsp/watcher/watcher.go +++ b/internal/lsp/watcher/watcher.go @@ -3,7 +3,6 @@ package watcher import ( "context" "fmt" - "log" "os" "path/filepath" "strings" @@ -11,11 +10,13 @@ import ( "time" "github.com/fsnotify/fsnotify" + "github.com/kujtimiihoxha/termai/internal/config" + "github.com/kujtimiihoxha/termai/internal/logging" "github.com/kujtimiihoxha/termai/internal/lsp" "github.com/kujtimiihoxha/termai/internal/lsp/protocol" ) -var debug = false // Force debug logging on +var logger = logging.Get() // WorkspaceWatcher manages LSP file watching type WorkspaceWatcher struct { @@ -43,6 +44,7 @@ func NewWorkspaceWatcher(client *lsp.Client) *WorkspaceWatcher { // AddRegistrations adds file watchers to track func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watchers []protocol.FileSystemWatcher) { + cnf := config.Get() w.registrationMu.Lock() defer w.registrationMu.Unlock() @@ -50,31 +52,35 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc w.registrations = append(w.registrations, watchers...) // Print detailed registration information for debugging - if debug { - log.Printf("Added %d file watcher registrations (id: %s), total: %d", - len(watchers), id, len(w.registrations)) + if cnf.Debug { + logger.Debug("Adding file watcher registrations", + "id", id, + "watchers", len(watchers), + "total", len(w.registrations), + "watchers", watchers, + ) for i, watcher := range watchers { - log.Printf("Registration #%d raw data:", i+1) + logger.Debug("Registration", "index", i+1) // Log the GlobPattern switch v := watcher.GlobPattern.Value.(type) { case string: - log.Printf(" GlobPattern: string pattern '%s'", v) + logger.Debug("GlobPattern", "pattern", v) case protocol.RelativePattern: - log.Printf(" GlobPattern: RelativePattern with pattern '%s'", v.Pattern) + logger.Debug("GlobPattern", "pattern", v.Pattern) // Log BaseURI details switch u := v.BaseURI.Value.(type) { case string: - log.Printf(" BaseURI: string '%s'", u) + logger.Debug("BaseURI", "baseURI", u) case protocol.DocumentUri: - log.Printf(" BaseURI: DocumentUri '%s'", u) + logger.Debug("BaseURI", "baseURI", u) default: - log.Printf(" BaseURI: unknown type %T", u) + logger.Debug("BaseURI", "baseURI", u) } default: - log.Printf(" GlobPattern: unknown type %T", v) + logger.Debug("GlobPattern", "unknown type", fmt.Sprintf("%T", v)) } // Log WatchKind @@ -82,11 +88,8 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc if watcher.Kind != nil { watchKind = *watcher.Kind } - log.Printf(" WatchKind: %d (Create:%v, Change:%v, Delete:%v)", - watchKind, - watchKind&protocol.WatchCreate != 0, - watchKind&protocol.WatchChange != 0, - watchKind&protocol.WatchDelete != 0) + + logger.Debug("WatchKind", "kind", watchKind) // Test match against some example paths testPaths := []string{ @@ -96,7 +99,7 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc for _, testPath := range testPaths { isMatch := w.matchesPattern(testPath, watcher.GlobPattern) - log.Printf(" Test path '%s': %v", testPath, isMatch) + logger.Debug("Test path", "path", testPath, "matches", isMatch) } } } @@ -114,10 +117,9 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc // Skip directories that should be excluded if d.IsDir() { - log.Println(path) if path != w.workspacePath && shouldExcludeDir(path) { - if debug { - log.Printf("Skipping excluded directory!!: %s", path) + if cnf.Debug { + logger.Debug("Skipping excluded directory", "path", path) } return filepath.SkipDir } @@ -136,18 +138,23 @@ func (w *WorkspaceWatcher) AddRegistrations(ctx context.Context, id string, watc }) elapsedTime := time.Since(startTime) - if debug { - log.Printf("Workspace scan complete: processed %d files in %.2f seconds", filesOpened, elapsedTime.Seconds()) + if cnf.Debug { + logger.Debug("Workspace scan complete", + "filesOpened", filesOpened, + "elapsedTime", elapsedTime.Seconds(), + "workspacePath", w.workspacePath, + ) } - if err != nil && debug { - log.Printf("Error scanning workspace for files to open: %v", err) + if err != nil && cnf.Debug { + logger.Debug("Error scanning workspace for files to open", "error", err) } }() } // WatchWorkspace sets up file watching for a workspace func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath string) { + cnf := config.Get() w.workspacePath = workspacePath // Register handler for file watcher registrations from the server @@ -157,7 +164,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str watcher, err := fsnotify.NewWatcher() if err != nil { - log.Fatalf("Error creating watcher: %v", err) + logger.Error("Error creating watcher", "error", err) } defer watcher.Close() @@ -170,8 +177,8 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str // Skip excluded directories (except workspace root) if d.IsDir() && path != workspacePath { if shouldExcludeDir(path) { - if debug { - log.Printf("Skipping watching excluded directory: %s", path) + if cnf.Debug { + logger.Debug("Skipping excluded directory", "path", path) } return filepath.SkipDir } @@ -181,14 +188,14 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str if d.IsDir() { err = watcher.Add(path) if err != nil { - log.Printf("Error watching path %s: %v", path, err) + logger.Error("Error watching path", "path", path, "error", err) } } return nil }) if err != nil { - log.Fatalf("Error walking workspace: %v", err) + logger.Error("Error walking workspace", "error", err) } // Event loop @@ -210,7 +217,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str // Skip excluded directories if !shouldExcludeDir(event.Name) { if err := watcher.Add(event.Name); err != nil { - log.Printf("Error watching new directory: %v", err) + logger.Error("Error adding directory to watcher", "path", event.Name, "error", err) } } } else { @@ -223,10 +230,15 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str } // Debug logging - if debug { + if cnf.Debug { matched, kind := w.isPathWatched(event.Name) - log.Printf("Event: %s, Op: %s, Watched: %v, Kind: %d", - event.Name, event.Op.String(), matched, kind) + logger.Debug("File event", + "path", event.Name, + "operation", event.Op.String(), + "watched", matched, + "kind", kind, + ) + } // Check if this path should be watched according to server registrations @@ -265,7 +277,7 @@ func (w *WorkspaceWatcher) WatchWorkspace(ctx context.Context, workspacePath str if !ok { return } - log.Printf("Watcher error: %v\n", err) + logger.Error("Error watching file", "error", err) } } } @@ -390,7 +402,7 @@ func matchesSimpleGlob(pattern, path string) bool { // Fall back to simple matching for simpler patterns matched, err := filepath.Match(pattern, path) if err != nil { - log.Printf("Error matching pattern %s: %v", pattern, err) + logger.Error("Error matching pattern", "pattern", pattern, "path", path, "error", err) return false } @@ -401,7 +413,7 @@ func matchesSimpleGlob(pattern, path string) bool { func (w *WorkspaceWatcher) matchesPattern(path string, pattern protocol.GlobPattern) bool { patternInfo, err := pattern.AsPattern() if err != nil { - log.Printf("Error parsing pattern: %v", err) + logger.Error("Error parsing pattern", "pattern", pattern, "error", err) return false } @@ -426,7 +438,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 { - log.Printf("Error getting relative path for %s: %v", path, err) + logger.Error("Error getting relative path", "path", path, "basePath", basePath, "error", err) return false } relPath = filepath.ToSlash(relPath) @@ -467,21 +479,25 @@ func (w *WorkspaceWatcher) handleFileEvent(ctx context.Context, uri string, chan if changeType == protocol.FileChangeType(protocol.Changed) && w.client.IsFileOpen(filePath) { err := w.client.NotifyChange(ctx, filePath) if err != nil { - log.Printf("Error notifying change: %v", err) + logger.Error("Error notifying change", "error", err) } return } // Notify LSP server about the file event using didChangeWatchedFiles if err := w.notifyFileEvent(ctx, uri, changeType); err != nil { - log.Printf("Error notifying LSP server about file event: %v", err) + logger.Error("Error notifying LSP server about file event", "error", err) } } // notifyFileEvent sends a didChangeWatchedFiles notification for a file event func (w *WorkspaceWatcher) notifyFileEvent(ctx context.Context, uri string, changeType protocol.FileChangeType) error { - if debug { - log.Printf("Notifying file event: %s (type: %d)", uri, changeType) + cnf := config.Get() + if cnf.Debug { + logger.Debug("Notifying file event", + "uri", uri, + "changeType", changeType, + ) } params := protocol.DidChangeWatchedFilesParams{ @@ -575,7 +591,7 @@ func shouldExcludeDir(dirPath string) bool { // shouldExcludeFile returns true if the file should be excluded from opening func shouldExcludeFile(filePath string) bool { fileName := filepath.Base(filePath) - + cnf := config.Get() // Skip dot files if strings.HasPrefix(fileName, ".") { return true @@ -601,8 +617,15 @@ func shouldExcludeFile(filePath string) bool { // Skip large files if info.Size() > maxFileSize { - if debug { - log.Printf("Skipping large file: %s (%.2f MB)", filePath, float64(info.Size())/(1024*1024)) + if cnf.Debug { + logger.Debug("Skipping large file", + "path", filePath, + "size", info.Size(), + "maxSize", maxFileSize, + "debug", cnf.Debug, + "sizeMB", float64(info.Size())/(1024*1024), + "maxSizeMB", float64(maxFileSize)/(1024*1024), + ) } return true } @@ -612,6 +635,7 @@ func shouldExcludeFile(filePath string) bool { // openMatchingFile opens a file if it matches any of the registered patterns func (w *WorkspaceWatcher) openMatchingFile(ctx context.Context, path string) { + cnf := config.Get() // Skip directories info, err := os.Stat(path) if err != nil || info.IsDir() { @@ -626,8 +650,8 @@ func (w *WorkspaceWatcher) openMatchingFile(ctx context.Context, path string) { // Check if this path should be watched according to server registrations if watched, _ := w.isPathWatched(path); watched { // Don't need to check if it's already open - the client.OpenFile handles that - if err := w.client.OpenFile(ctx, path); err != nil && debug { - log.Printf("Error opening file %s: %v", path, err) + if err := w.client.OpenFile(ctx, path); err != nil && cnf.Debug { + logger.Error("Error opening file", "path", path, "error", err) } } } |
