@@ -9,24 +9,34 @@ import (
9
9
10
10
"github.com/docker/docker-language-server/internal/pkg/document"
11
11
"github.com/docker/docker-language-server/internal/tliron/glsp/protocol"
12
+ "github.com/goccy/go-yaml/ast"
12
13
"github.com/santhosh-tekuri/jsonschema/v6"
13
- "gopkg.in/yaml.v3"
14
14
)
15
15
16
16
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
+
17
22
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
+ }
24
34
}
25
35
return nil , nil
26
36
}
27
37
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 {
30
40
if schema .Ref != nil {
31
41
schema = schema .Ref
32
42
}
@@ -35,22 +45,29 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
35
45
for _ , n := range nested .OneOf {
36
46
if n .Types != nil && slices .Contains (n .Types .ToStrings (), "object" ) {
37
47
if len (n .Properties ) > 0 {
38
- if _ , ok := n .Properties [node .Value ]; ok {
48
+ if _ , ok := n .Properties [match . GetToken () .Value ]; ok {
39
49
schema = n
40
50
break
41
51
}
42
52
}
43
53
}
44
54
}
45
55
46
- if _ , ok := nested .Properties [node .Value ]; ok {
56
+ if _ , ok := nested .Properties [match . GetToken () .Value ]; ok {
47
57
schema = nested
48
58
}
49
59
}
50
60
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 {
52
69
if property .Enum != nil {
53
- if node .Column <= column && column <= lineLength {
70
+ if match . GetToken (). Position .Column <= column && column <= lineLength {
54
71
var builder bytes.Buffer
55
72
builder .WriteString ("Allowed values:\n " )
56
73
enumValues := []string {}
@@ -70,7 +87,7 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
70
87
}
71
88
}
72
89
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 != "" {
74
91
return & protocol.Hover {
75
92
Contents : protocol.MarkupContent {
76
93
Kind : protocol .MarkupKindPlainText ,
@@ -79,10 +96,11 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
79
96
}
80
97
}
81
98
schema = property
99
+ continue
82
100
}
83
101
84
102
for regexp , property := range schema .PatternProperties {
85
- if regexp .MatchString (node .Value ) {
103
+ if regexp .MatchString (match . GetToken () .Value ) {
86
104
if property .Ref == nil {
87
105
schema = property
88
106
} else {
@@ -91,13 +109,43 @@ func hoverLookup(schema *jsonschema.Schema, nodes []*yaml.Node, line, column, li
91
109
break
92
110
}
93
111
}
112
+ }
113
+ return nil
114
+ }
94
115
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
99
128
}
100
129
}
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 }
101
149
}
102
150
return nil
103
151
}
0 commit comments