Skip to content

Commit aa22f86

Browse files
shyimclaude
andcommitted
feat: implement hover support for LSP
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 89ec5ab commit aa22f86

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed

internal/lsp/hover.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package lsp
2+
3+
import (
4+
"context"
5+
"path/filepath"
6+
7+
"github.com/shopware/shopware-lsp/internal/lsp/protocol"
8+
"github.com/shopware/shopware-lsp/internal/php"
9+
)
10+
11+
// hover handles textDocument/hover requests
12+
func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*protocol.Hover, error) {
13+
node, docText, ok := s.documentManager.GetNodeAtPosition(params.TextDocument.URI, params.Position.Line, params.Position.Character)
14+
if ok {
15+
params.Node = node
16+
params.DocumentContent = docText.Text
17+
18+
if filepath.Ext(params.TextDocument.URI) == ".php" {
19+
phpIndex, _ := s.GetIndexer("php.index")
20+
ctx = phpIndex.(*php.PHPIndex).AddContext(ctx, node, docText.Text)
21+
}
22+
}
23+
24+
// Try each hover provider until one returns a result
25+
for _, provider := range s.hoverProviders {
26+
hover, err := provider.GetHover(ctx, params)
27+
if err != nil {
28+
continue
29+
}
30+
if hover != nil {
31+
return hover, nil
32+
}
33+
}
34+
35+
// No hover information available
36+
return nil, nil
37+
}

internal/lsp/protocol/hover.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package protocol
2+
3+
import tree_sitter "github.com/tree-sitter/go-tree-sitter"
4+
5+
// HoverParams represents the parameters for a hover request
6+
type HoverParams struct {
7+
TextDocument struct {
8+
URI string `json:"uri"`
9+
} `json:"textDocument"`
10+
Position struct {
11+
Line int `json:"line"`
12+
Character int `json:"character"`
13+
} `json:"position"`
14+
WorkDoneToken interface{} `json:"workDoneToken,omitempty"`
15+
16+
// Custom fields for internal use (not part of LSP spec)
17+
// These fields are used to pass document content to hover providers
18+
DocumentContent []byte `json:"-"`
19+
Node *tree_sitter.Node `json:"-"`
20+
}
21+
22+
// Hover represents the result of a hover request
23+
type Hover struct {
24+
// The hover's content
25+
Contents MarkupContent `json:"contents"`
26+
27+
// An optional range inside the text document that is used to
28+
// visualize the hover, e.g. by changing the background color
29+
Range *Range `json:"range,omitempty"`
30+
}
31+
32+
// MarkupContent represents a string value which content is interpreted based on its kind flag
33+
type MarkupContent struct {
34+
// The type of the Markup
35+
Kind MarkupKind `json:"kind"`
36+
37+
// The content itself
38+
Value string `json:"value"`
39+
}
40+
41+
// MarkupKind describes the content type that a client supports in various
42+
// result literals like `Hover`, `ParameterInfo` or `CompletionItem`
43+
type MarkupKind string
44+
45+
const (
46+
// PlainText plain text is supported as a content format
47+
PlainText MarkupKind = "plaintext"
48+
49+
// Markdown markdown is supported as a content format
50+
Markdown MarkupKind = "markdown"
51+
)

internal/lsp/server.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Server struct {
2727
codeLensProviders []CodeLensProvider
2828
diagnosticsProviders []DiagnosticsProvider
2929
codeActionProviders []CodeActionProvider
30+
hoverProviders []HoverProvider
3031
commandProviders []CommandProvider
3132
indexers map[string]indexer.Indexer
3233
commandMap map[string]CommandFunc
@@ -46,6 +47,7 @@ func NewServer(filescanner *indexer.FileScanner, cacheDir, version string) *Serv
4647
codeLensProviders: make([]CodeLensProvider, 0),
4748
diagnosticsProviders: make([]DiagnosticsProvider, 0),
4849
codeActionProviders: make([]CodeActionProvider, 0),
50+
hoverProviders: make([]HoverProvider, 0),
4951
commandProviders: make([]CommandProvider, 0),
5052
indexers: make(map[string]indexer.Indexer),
5153
commandMap: make(map[string]CommandFunc),
@@ -89,6 +91,11 @@ func (s *Server) RegisterCodeActionProvider(provider CodeActionProvider) {
8991
s.codeActionProviders = append(s.codeActionProviders, provider)
9092
}
9193

94+
// RegisterHoverProvider registers a hover provider with the server
95+
func (s *Server) RegisterHoverProvider(provider HoverProvider) {
96+
s.hoverProviders = append(s.hoverProviders, provider)
97+
}
98+
9299
// RegisterCommandProvider registers a command provider with the server
93100
func (s *Server) RegisterCommandProvider(provider CommandProvider) {
94101
s.commandProviders = append(s.commandProviders, provider)
@@ -355,6 +362,13 @@ func (s *Server) handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.
355362
}
356363
return s.codeLens(ctx, &params), nil
357364

365+
case "textDocument/hover":
366+
var params protocol.HoverParams
367+
if err := json.Unmarshal(*req.Params, &params); err != nil {
368+
return nil, err
369+
}
370+
return s.hover(ctx, &params)
371+
358372
case "textDocument/diagnostic":
359373
var params protocol.DiagnosticParams
360374
if err := json.Unmarshal(*req.Params, &params); err != nil {
@@ -539,6 +553,7 @@ func (s *Server) initialize(ctx context.Context, params *protocol.InitializePara
539553
},
540554
"definitionProvider": true,
541555
"referencesProvider": true,
556+
"hoverProvider": true,
542557
"codeLensProvider": map[string]interface{}{
543558
"resolveProvider": true,
544559
},

internal/lsp/types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ type CompletionProvider interface {
1515
GetTriggerCharacters() []string
1616
}
1717

18+
// HoverProvider is an interface for providing hover information
19+
type HoverProvider interface {
20+
// GetHover returns hover information for the given parameters
21+
GetHover(ctx context.Context, params *protocol.HoverParams) (*protocol.Hover, error)
22+
}
23+
1824
// CodeLensProvider is an interface for providing code lenses
1925
type CodeLensProvider interface {
2026
// GetCodeLenses returns code lenses for the given document

0 commit comments

Comments
 (0)