1
1
package compose
2
2
3
3
import (
4
+ "strings"
5
+
4
6
"github.com/docker/docker-language-server/internal/pkg/document"
5
7
"github.com/docker/docker-language-server/internal/tliron/glsp/protocol"
6
8
"github.com/goccy/go-yaml/ast"
7
9
"github.com/goccy/go-yaml/token"
8
10
)
9
11
10
- func serviceReferences (node * ast.MappingValueNode , dependencyAttributeName string ) []* token.Token {
12
+ func serviceDependencyReferences (node * ast.MappingValueNode , dependencyAttributeName string , arrayOnly bool ) []* token.Token {
11
13
if servicesNode , ok := node .Value .(* ast.MappingNode ); ok {
12
14
tokens := []* token.Token {}
13
15
for _ , serviceNode := range servicesNode .Values {
@@ -18,8 +20,52 @@ func serviceReferences(node *ast.MappingValueNode, dependencyAttributeName strin
18
20
for _ , service := range sequenceNode .Values {
19
21
tokens = append (tokens , service .GetToken ())
20
22
}
21
- } else if dependentService , ok := attributeNode .Value .(* ast.StringNode ); ok {
22
- tokens = append (tokens , dependentService .GetToken ())
23
+ } else if ! arrayOnly {
24
+ if mappingNode , ok := attributeNode .Value .(* ast.MappingNode ); ok {
25
+ for _ , dependentService := range mappingNode .Values {
26
+ tokens = append (tokens , dependentService .Key .GetToken ())
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ return tokens
35
+ }
36
+ return nil
37
+ }
38
+
39
+ func volumeToken (t * token.Token ) * token.Token {
40
+ idx := strings .Index (t .Value , ":" )
41
+ if idx != - 1 {
42
+ return & token.Token {
43
+ Value : t .Value [0 :idx ],
44
+ Position : t .Position ,
45
+ }
46
+ }
47
+ return t
48
+ }
49
+
50
+ func volumeReferences (node * ast.MappingValueNode ) []* token.Token {
51
+ if servicesNode , ok := node .Value .(* ast.MappingNode ); ok {
52
+ tokens := []* token.Token {}
53
+ for _ , serviceNode := range servicesNode .Values {
54
+ if serviceAttributes , ok := serviceNode .Value .(* ast.MappingNode ); ok {
55
+ for _ , attributeNode := range serviceAttributes .Values {
56
+ if attributeNode .Key .GetToken ().Value == "volumes" {
57
+ if sequenceNode , ok := attributeNode .Value .(* ast.SequenceNode ); ok {
58
+ for _ , service := range sequenceNode .Values {
59
+ if volumeObjectNode , ok := service .(* ast.MappingNode ); ok {
60
+ for _ , volumeAttribute := range volumeObjectNode .Values {
61
+ if volumeAttribute .Key .GetToken ().Value == "source" {
62
+ tokens = append (tokens , volumeAttribute .Value .GetToken ())
63
+ }
64
+ }
65
+ } else {
66
+ tokens = append (tokens , volumeToken (service .GetToken ()))
67
+ }
68
+ }
23
69
} else if mappingNode , ok := attributeNode .Value .(* ast.MappingNode ); ok {
24
70
for _ , dependentService := range mappingNode .Values {
25
71
tokens = append (tokens , dependentService .Key .GetToken ())
@@ -56,51 +102,88 @@ func DocumentHighlight(doc document.ComposeDocument, position protocol.Position)
56
102
line := int (position .Line ) + 1
57
103
character := int (position .Character ) + 1
58
104
if mappingNode , ok := file .Docs [0 ].Body .(* ast.MappingNode ); ok {
105
+ var networkRefs []* token.Token
106
+ var volumeRefs []* token.Token
107
+ var configRefs []* token.Token
108
+ var secretRefs []* token.Token
109
+ var networkDeclarations []* token.Token
110
+ var volumeDeclarations []* token.Token
111
+ var configDeclarations []* token.Token
112
+ var secretDeclarations []* token.Token
59
113
for _ , node := range mappingNode .Values {
60
114
if s , ok := node .Key .(* ast.StringNode ); ok {
61
115
switch s .Value {
62
116
case "services" :
63
- refs := serviceReferences (node , "depends_on" )
117
+ refs := serviceDependencyReferences (node , "depends_on" , false )
64
118
decls := declarations (node , "services" )
65
- highlights := highlightServiceReferences (refs , decls , line , character )
119
+ highlights := highlightReferences (refs , decls , line , character )
66
120
if len (highlights ) > 0 {
67
121
return highlights , nil
68
122
}
123
+ networkRefs = serviceDependencyReferences (node , "networks" , false )
124
+ configRefs = serviceDependencyReferences (node , "configs" , true )
125
+ secretRefs = serviceDependencyReferences (node , "secrets" , true )
126
+ volumeRefs = volumeReferences (node )
127
+ case "networks" :
128
+ networkDeclarations = declarations (node , "networks" )
129
+ case "volumes" :
130
+ volumeDeclarations = declarations (node , "volumes" )
131
+ case "configs" :
132
+ configDeclarations = declarations (node , "configs" )
133
+ case "secrets" :
134
+ secretDeclarations = declarations (node , "secrets" )
69
135
}
70
136
}
71
137
}
138
+ highlights := highlightReferences (networkRefs , networkDeclarations , line , character )
139
+ if len (highlights ) > 0 {
140
+ return highlights , nil
141
+ }
142
+ highlights = highlightReferences (volumeRefs , volumeDeclarations , line , character )
143
+ if len (highlights ) > 0 {
144
+ return highlights , nil
145
+ }
146
+ highlights = highlightReferences (configRefs , configDeclarations , line , character )
147
+ if len (highlights ) > 0 {
148
+ return highlights , nil
149
+ }
150
+ highlights = highlightReferences (secretRefs , secretDeclarations , line , character )
151
+ if len (highlights ) > 0 {
152
+ return highlights , nil
153
+ }
154
+ return highlights , nil
72
155
}
73
156
return nil , nil
74
157
}
75
158
76
- func highlightServiceReferences (refs , decls []* token.Token , line , character int ) []protocol.DocumentHighlight {
77
- var match * token. Token
159
+ func highlightReferences (refs , decls []* token.Token , line , character int ) []protocol.DocumentHighlight {
160
+ var highlightedName * string
78
161
for _ , reference := range refs {
79
162
if inToken (reference , line , character ) {
80
- match = reference
163
+ highlightedName = & reference . Value
81
164
break
82
165
}
83
166
}
84
167
85
- if match == nil {
168
+ if highlightedName == nil {
86
169
for _ , declaration := range decls {
87
170
if inToken (declaration , line , character ) {
88
- match = declaration
171
+ highlightedName = & declaration . Value
89
172
break
90
173
}
91
174
}
92
175
}
93
176
94
- if match != nil {
177
+ if highlightedName != nil {
95
178
highlights := []protocol.DocumentHighlight {}
96
179
for _ , reference := range refs {
97
- if reference .Value == match . Value {
180
+ if reference .Value == * highlightedName {
98
181
highlights = append (highlights , documentHighlightFromToken (reference , protocol .DocumentHighlightKindRead ))
99
182
}
100
183
}
101
184
102
185
for _ , declaration := range decls {
103
- if declaration .Value == match . Value {
186
+ if declaration .Value == * highlightedName {
104
187
highlights = append (highlights , documentHighlightFromToken (declaration , protocol .DocumentHighlightKindWrite ))
105
188
}
106
189
}
0 commit comments