summaryrefslogtreecommitdiff
path: root/internal/lsp/handlers_codeaction.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-17 11:28:19 +0200
committerPaul Buetow <paul@buetow.org>2026-03-17 11:28:19 +0200
commit6f1c8bf7a36eb7044ed7aad30f84664cbbf0d303 (patch)
treedd2ac6e1433177fb59c167a12fa0b4b91132f34a /internal/lsp/handlers_codeaction.go
parent10562cc510f64d5ac38aeb76f03e18eb76cca40f (diff)
Fix bugs, remove duplication, and clean up code quality issues
- Log swallowed JSON unmarshal errors in stats and LSP handlers - Fix debug log file handle leak in tmuxedit (return closer from initDebugLog) - Check f.Close() errors on write paths in promptstore and tmuxedit - Fix cacheGet TOCTOU race by using single write lock - Fix readInput to use passed stdin reader instead of os.Stdin.Stat() - Remove 45 'moved to' comment tombstones from lsp/handlers.go - Deduplicate canonicalProvider wrappers (use llmutils.CanonicalProvider directly) - Remove SetWindow side effect from stats.TakeSnapshot (pure read now) - Move duplicated splitLines to textutil.SplitLinesBytes - Collapse StatusSink.SetGlobal 10 params into GlobalStatus struct - Simplify LRU touchLocked to in-place delete-and-append Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'internal/lsp/handlers_codeaction.go')
-rw-r--r--internal/lsp/handlers_codeaction.go95
1 files changed, 55 insertions, 40 deletions
diff --git a/internal/lsp/handlers_codeaction.go b/internal/lsp/handlers_codeaction.go
index 8b16fcd..1d8a36f 100644
--- a/internal/lsp/handlers_codeaction.go
+++ b/internal/lsp/handlers_codeaction.go
@@ -25,6 +25,15 @@ type codeActionPayload struct {
Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
}
+type customActionPayload struct {
+ Type string `json:"type"`
+ ID string `json:"id"`
+ URI string `json:"uri"`
+ Range Range `json:"range"`
+ Selection string `json:"selection"`
+ Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
+}
+
// CodeActionHandler builds and resolves code actions for a specific action type.
type CodeActionHandler interface {
Build(s *Server, p CodeActionParams, selection string) []CodeAction
@@ -103,58 +112,64 @@ func (s *Server) appendCustomActions(actions *[]CodeAction, p CodeActionParams,
return
}
diags := s.diagnosticsInRange(p.Context, p.Range)
+
for _, ca := range customs {
title := strings.TrimSpace(ca.Title)
if title == "" {
continue
}
+
scope := strings.TrimSpace(strings.ToLower(ca.Scope))
if scope == "diagnostics" {
- if len(diags) == 0 {
- continue
- }
- payload := struct {
- Type string `json:"type"`
- ID string `json:"id"`
- URI string `json:"uri"`
- Range Range `json:"range"`
- Selection string `json:"selection"`
- Diagnostics []Diagnostic `json:"diagnostics"`
- }{Type: "custom", ID: ca.ID, URI: p.TextDocument.URI, Range: p.Range, Selection: sel, Diagnostics: diags}
- raw, ok := s.marshalCodeActionData(payload)
- if !ok {
- continue
- }
- kind := ca.Kind
- if strings.TrimSpace(kind) == "" {
- kind = "quickfix"
- }
- *actions = append(*actions, CodeAction{Title: "Hexai: " + title, Kind: kind, Data: raw})
- continue
- }
- // default: selection
- if strings.TrimSpace(sel) == "" {
- continue
- }
- payload := struct {
- Type string `json:"type"`
- ID string `json:"id"`
- URI string `json:"uri"`
- Range Range `json:"range"`
- Selection string `json:"selection"`
- }{Type: "custom", ID: ca.ID, URI: p.TextDocument.URI, Range: p.Range, Selection: sel}
- raw, ok := s.marshalCodeActionData(payload)
- if !ok {
- continue
- }
- kind := ca.Kind
- if strings.TrimSpace(kind) == "" {
- kind = "refactor"
+ s.appendCustomActionForDiagnostics(actions, p, sel, diags, ca, title)
+ } else {
+ s.appendCustomActionForSelection(actions, p, sel, ca, title)
}
+ }
+}
+
+func (s *Server) appendCustomActionForDiagnostics(actions *[]CodeAction, p CodeActionParams, sel string, diags []Diagnostic, ca appconfig.CustomAction, title string) {
+ if len(diags) == 0 {
+ return
+ }
+ payload := customActionPayload{
+ Type: "custom",
+ ID: ca.ID,
+ URI: p.TextDocument.URI,
+ Range: p.Range,
+ Selection: sel,
+ Diagnostics: diags,
+ }
+ if raw, ok := s.marshalCodeActionData(payload); ok {
+ kind := s.resolveCodeActionKind(ca.Kind, "quickfix")
+ *actions = append(*actions, CodeAction{Title: "Hexai: " + title, Kind: kind, Data: raw})
+ }
+}
+
+func (s *Server) appendCustomActionForSelection(actions *[]CodeAction, p CodeActionParams, sel string, ca appconfig.CustomAction, title string) {
+ if strings.TrimSpace(sel) == "" {
+ return
+ }
+ payload := customActionPayload{
+ Type: "custom",
+ ID: ca.ID,
+ URI: p.TextDocument.URI,
+ Range: p.Range,
+ Selection: sel,
+ }
+ if raw, ok := s.marshalCodeActionData(payload); ok {
+ kind := s.resolveCodeActionKind(ca.Kind, "refactor")
*actions = append(*actions, CodeAction{Title: "Hexai: " + title, Kind: kind, Data: raw})
}
}
+func (s *Server) resolveCodeActionKind(kind, fallback string) string {
+ if strings.TrimSpace(kind) == "" {
+ return fallback
+ }
+ return kind
+}
+
func (s *Server) codeActionHandlers() map[string]CodeActionHandler {
return map[string]CodeActionHandler{
"rewrite": codeActionHandler{build: buildRewriteActions, resolve: resolveRewriteCodeAction},