Skip to content

Commit 4faa08b

Browse files
tx3stndaveshanley
authored andcommitted
add code action to open documentation url
1 parent daed78a commit 4faa08b

File tree

3 files changed

+62
-18
lines changed

3 files changed

+62
-18
lines changed

language-server/server.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ func NewServer(version string, lintRequest *utils.LintFileRequest) *ServerState
5555
serverCapabilities := handler.CreateServerCapabilities()
5656
serverCapabilities.TextDocumentSync = protocol.TextDocumentSyncKindIncremental
5757
serverCapabilities.CompletionProvider = &protocol.CompletionOptions{}
58+
serverCapabilities.CodeActionProvider = &protocol.CodeActionOptions{
59+
CodeActionKinds: []protocol.CodeActionKind{protocol.CodeActionKindQuickFix},
60+
}
61+
serverCapabilities.ExecuteCommandProvider = &protocol.ExecuteCommandOptions{
62+
Commands: []string{"vacuum.openUrl"},
63+
}
5864

5965
return protocol.InitializeResult{
6066
Capabilities: serverCapabilities,
@@ -99,6 +105,36 @@ func NewServer(version string, lintRequest *utils.LintFileRequest) *ServerState
99105
handler.TextDocumentCompletion = func(context *glsp.Context, params *protocol.CompletionParams) (any, error) {
100106
return nil, nil
101107
}
108+
109+
handler.TextDocumentCodeAction = func(context *glsp.Context, params *protocol.CodeActionParams) (any, error) {
110+
var actions []protocol.CodeAction
111+
112+
for _, diagnostic := range params.Context.Diagnostics {
113+
if diagnostic.CodeDescription != nil && diagnostic.CodeDescription.HRef != "" {
114+
quickFixKind := protocol.CodeActionKindQuickFix
115+
actions = append(actions, protocol.CodeAction{
116+
Title: "View documentation",
117+
Kind: &quickFixKind,
118+
Command: &protocol.Command{
119+
Title: "Open documentation",
120+
Command: "vacuum.openUrl",
121+
Arguments: []interface{}{diagnostic.CodeDescription.HRef},
122+
},
123+
})
124+
}
125+
}
126+
127+
return actions, nil
128+
}
129+
130+
handler.WorkspaceExecuteCommand = func(context *glsp.Context, params *protocol.ExecuteCommandParams) (any, error) {
131+
if params.Command == "vacuum.openUrl" && len(params.Arguments) > 0 {
132+
if url, ok := params.Arguments[0].(string); ok {
133+
utils.OpenURL(url)
134+
}
135+
}
136+
return nil, nil
137+
}
102138
return state
103139
}
104140

@@ -166,7 +202,9 @@ func ConvertResultIntoDiagnostic(vacuumResult *model.RuleFunctionResult) protoco
166202
severity := GetDiagnosticSeverityFromRule(vacuumResult.Rule)
167203

168204
diagnosticErrorHref := fmt.Sprintf("%s/rules/unknown", model.WebsiteUrl)
169-
if vacuumResult.Rule.RuleCategory != nil {
205+
if vacuumResult.Rule.DocumentationURL != "" {
206+
diagnosticErrorHref = vacuumResult.Rule.DocumentationURL
207+
} else if vacuumResult.Rule.RuleCategory != nil {
170208
diagnosticErrorHref = fmt.Sprintf("%s/rules/%s/%s", model.WebsiteUrl,
171209
strings.ToLower(vacuumResult.Rule.RuleCategory.Id),
172210
strings.ReplaceAll(strings.ToLower(vacuumResult.Rule.Id), "$", ""))
@@ -191,7 +229,7 @@ func ConvertResultIntoDiagnostic(vacuumResult *model.RuleFunctionResult) protoco
191229
message += "\n\nDescription: " + vacuumResult.Rule.Description
192230
}
193231
if vacuumResult.Rule.HowToFix != "" {
194-
message += "\n\nHow to fix: " + vacuumResult.Rule.HowToFix + "\n\nRule ID:"
232+
message += "\n\nHow to fix: " + vacuumResult.Rule.HowToFix + "\n\nRule ID: " + vacuumResult.Rule.Id + "\n"
195233
}
196234

197235
return protocol.Diagnostic{

tui/lint_details_table_render.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ package tui
55

66
import (
77
"fmt"
8-
"os/exec"
9-
"runtime"
108
"strings"
119

1210
tea "github.com/charmbracelet/bubbletea/v2"
1311
"github.com/charmbracelet/glamour"
1412
"github.com/daveshanley/vacuum/color"
13+
"github.com/daveshanley/vacuum/utils"
1514
"github.com/muesli/termenv"
1615
)
1716

@@ -330,20 +329,7 @@ func (m *ViolationResultTableModel) fetchDocumentation(ruleID string) tea.Cmd {
330329
// If it's not the default quobix.com pattern, open in browser
331330
if !strings.Contains(customURL, "quobix.com/vacuum/rules/") {
332331
return func() tea.Msg {
333-
// Open URL in default browser
334-
var cmd *exec.Cmd
335-
switch runtime.GOOS {
336-
case "linux":
337-
cmd = exec.Command("xdg-open", customURL)
338-
case "windows":
339-
cmd = exec.Command("rundll32", "url.dll,FileProtocolHandler", customURL)
340-
case "darwin":
341-
cmd = exec.Command("open", customURL)
342-
default:
343-
return docsErrorMsg{ruleID: ruleID, err: "Unsupported platform for opening browser", is404: false}
344-
}
345-
346-
if err := cmd.Start(); err != nil {
332+
if err := utils.OpenURL(customURL); err != nil {
347333
return docsErrorMsg{ruleID: ruleID, err: fmt.Sprintf("Failed to open browser: %s", err.Error()), is404: false}
348334
}
349335

utils/open_url.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package utils
2+
3+
import (
4+
"os/exec"
5+
"runtime"
6+
)
7+
8+
// OpenURL opens the given URL in the system's default browser
9+
func OpenURL(url string) error {
10+
var cmd *exec.Cmd
11+
switch runtime.GOOS {
12+
case "windows":
13+
cmd = exec.Command("rundll32", "url.dll,FileProtocolHandler", url)
14+
case "darwin":
15+
cmd = exec.Command("open", url)
16+
default:
17+
cmd = exec.Command("xdg-open", url)
18+
}
19+
return cmd.Start()
20+
}

0 commit comments

Comments
 (0)