Skip to content

Commit c5fb845

Browse files
committed
Refactor Compose hover code to goccy/go-yaml
Signed-off-by: Remy Suen <[email protected]>
1 parent 2085778 commit c5fb845

File tree

4 files changed

+69
-27
lines changed

4 files changed

+69
-27
lines changed

internal/compose/documentLink.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,6 @@ func DocumentLink(ctx context.Context, documentURI protocol.URI, doc document.Co
143143
for _, node := range mappingNode.Values {
144144
links = append(links, scanForLinks(url, node)...)
145145
}
146-
} else if mappingNodeValue, ok := documentNode.Body.(*ast.MappingValueNode); ok {
147-
links = append(links, scanForLinks(url, mappingNodeValue)...)
148146
}
149147
}
150148
return links, nil

internal/compose/documentSymbol.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,7 @@ func DocumentSymbol(ctx context.Context, doc document.ComposeDocument) (result [
4343
}
4444

4545
for _, documentNode := range file.Docs {
46-
if n, ok := documentNode.Body.(*ast.MappingValueNode); ok {
47-
if s, ok := n.Key.(*ast.StringNode); ok {
48-
result = append(result, findSymbols(s.Value, n, symbolKinds)...)
49-
}
50-
} else if mappingNode, ok := documentNode.Body.(*ast.MappingNode); ok {
46+
if mappingNode, ok := documentNode.Body.(*ast.MappingNode); ok {
5147
for _, n := range mappingNode.Values {
5248
if s, ok := n.Key.(*ast.StringNode); ok {
5349
result = append(result, findSymbols(s.Value, n, symbolKinds)...)

internal/compose/hover.go

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,34 @@ import (
99

1010
"github.com/docker/docker-language-server/internal/pkg/document"
1111
"github.com/docker/docker-language-server/internal/tliron/glsp/protocol"
12+
"github.com/goccy/go-yaml/ast"
1213
"github.com/santhosh-tekuri/jsonschema/v6"
13-
"gopkg.in/yaml.v3"
1414
)
1515

1616
func Hover(ctx context.Context, params *protocol.HoverParams, doc document.ComposeDocument) (*protocol.Hover, error) {
17+
file := doc.File()
18+
if file == nil || len(file.Docs) == 0 {
19+
return nil, nil
20+
}
21+
1722
line := int(params.Position.Line) + 1
18-
root := doc.RootNode()
19-
if len(root.Content) > 0 {
20-
lines := strings.Split(string(doc.Input()), "\n")
21-
character := int(params.Position.Character) + 1
22-
topLevel, _, _ := NodeStructure(line, root.Content[0].Content)
23-
return hoverLookup(composeSchema, topLevel, line, character, len(lines[params.Position.Line])+1), nil
23+
character := int(params.Position.Character) + 1
24+
lines := strings.Split(string(doc.Input()), "\n")
25+
26+
for _, documentNode := range file.Docs {
27+
if mappingNode, ok := documentNode.Body.(*ast.MappingNode); ok {
28+
m := constructNodePath([]ast.Node{}, mappingNode, int(params.Position.Line+1), int(params.Position.Character+1))
29+
hover := hover(composeSchema, m, line, character, len(lines[params.Position.Line])+1)
30+
if hover != nil {
31+
return hover, nil
32+
}
33+
}
2434
}
2535
return nil, nil
2636
}
2737

28-
func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, lineLength int) *protocol.Hover {
29-
for _, node := range nodes {
38+
func hover(schema *jsonschema.Schema, nodes []ast.Node, line, column, lineLength int) *protocol.Hover {
39+
for _, match := range nodes {
3040
if schema.Ref != nil {
3141
schema = schema.Ref
3242
}
@@ -35,22 +45,29 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
3545
for _, n := range nested.OneOf {
3646
if n.Types != nil && slices.Contains(n.Types.ToStrings(), "object") {
3747
if len(n.Properties) > 0 {
38-
if _, ok := n.Properties[node.Value]; ok {
48+
if _, ok := n.Properties[match.GetToken().Value]; ok {
3949
schema = n
4050
break
4151
}
4252
}
4353
}
4454
}
4555

46-
if _, ok := nested.Properties[node.Value]; ok {
56+
if _, ok := nested.Properties[match.GetToken().Value]; ok {
4757
schema = nested
4858
}
4959
}
5060

51-
if property, ok := schema.Properties[node.Value]; ok {
61+
for _, nested := range schema.OneOf {
62+
if nested.Types != nil && slices.Contains(nested.Types.ToStrings(), "object") {
63+
schema = nested
64+
break
65+
}
66+
}
67+
68+
if property, ok := schema.Properties[match.GetToken().Value]; ok {
5269
if property.Enum != nil {
53-
if node.Column <= column && column <= lineLength {
70+
if match.GetToken().Position.Column <= column && column <= lineLength {
5471
var builder bytes.Buffer
5572
builder.WriteString("Allowed values:\n")
5673
enumValues := []string{}
@@ -70,7 +87,7 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
7087
}
7188
}
7289

73-
if node.Line == line && node.Column+len(node.Value) >= column && property.Description != "" {
90+
if match.GetToken().Position.Line == line && match.GetToken().Position.Column+len(match.GetToken().Value) >= column && property.Description != "" {
7491
return &protocol.Hover{
7592
Contents: protocol.MarkupContent{
7693
Kind: protocol.MarkupKindPlainText,
@@ -79,10 +96,11 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
7996
}
8097
}
8198
schema = property
99+
continue
82100
}
83101

84102
for regexp, property := range schema.PatternProperties {
85-
if regexp.MatchString(node.Value) {
103+
if regexp.MatchString(match.GetToken().Value) {
86104
if property.Ref == nil {
87105
schema = property
88106
} else {
@@ -91,13 +109,43 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
91109
break
92110
}
93111
}
112+
}
113+
return nil
114+
}
94115

95-
for _, nested := range schema.OneOf {
96-
if nested.Types != nil && slices.Contains(nested.Types.ToStrings(), "object") {
97-
schema = nested
98-
break
116+
func constructNodePath(matches []ast.Node, node ast.Node, line, col int) []ast.Node {
117+
switch n := node.(type) {
118+
case *ast.MappingValueNode:
119+
if keyNode, ok := n.Key.(*ast.StringNode); ok {
120+
if m := constructNodePath(matches, n.Key, line, col); m != nil {
121+
matches = append(matches, m...)
122+
return matches
123+
}
124+
if m := constructNodePath(matches, n.Value, line, col); m != nil {
125+
matches = append(matches, keyNode)
126+
matches = append(matches, m...)
127+
return matches
99128
}
100129
}
130+
case *ast.MappingNode:
131+
for _, kv := range n.Values {
132+
if m := constructNodePath(matches, kv, line, col); m != nil {
133+
matches = append(matches, m...)
134+
return matches
135+
}
136+
}
137+
case *ast.SequenceNode:
138+
for _, item := range n.Values {
139+
if m := constructNodePath(matches, item, line, col); m != nil {
140+
matches = append(matches, m...)
141+
return matches
142+
}
143+
}
144+
}
145+
146+
token := node.GetToken()
147+
if token.Position.Line == line && token.Position.Column <= col && col <= token.Position.Column+len(token.Value) {
148+
return []ast.Node{node}
101149
}
102150
return nil
103151
}

internal/compose/hover_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func TestHover(t *testing.T) {
7474
},
7575
{
7676
name: "incomplete node",
77-
content: "hello",
77+
content: "version",
7878
line: 0,
7979
character: 2,
8080
result: nil,

0 commit comments

Comments
 (0)