@@ -3,6 +3,7 @@ package compose
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "os"
6
7
"path/filepath"
7
8
"slices"
8
9
"strings"
@@ -213,7 +214,8 @@ func Completion(ctx context.Context, params *protocol.CompletionParams, manager
213
214
whitespaceLine := currentLineTrimmed == ""
214
215
line := int (lspLine ) + 1
215
216
path := constructCompletionNodePath (file , line )
216
- wordPrefix := protocol .UInteger (len (prefix (lines [lspLine ], character - 1 )))
217
+ prefixContent := prefix (lines [lspLine ], character - 1 )
218
+ prefixLength := protocol .UInteger (len (prefixContent ))
217
219
if len (path ) == 0 {
218
220
if topLevelNodeOffset != - 1 && params .Position .Character != uint32 (topLevelNodeOffset ) {
219
221
return nil , nil
@@ -222,7 +224,7 @@ func Completion(ctx context.Context, params *protocol.CompletionParams, manager
222
224
} else if len (path ) == 1 {
223
225
if path [0 ].Key .GetToken ().Value == "include" {
224
226
schema := schemaProperties ()["include" ].Items .(* jsonschema.Schema )
225
- items := createSchemaItems (params , schema .Ref .OneOf [1 ].Properties , lines , lspLine , whitespaceLine , wordPrefix , file , manager , documentPath , path )
227
+ items := createSchemaItems (params , schema .Ref .OneOf [1 ].Properties , lines , lspLine , whitespaceLine , prefixLength , file , manager , documentPath , path )
226
228
return processItems (items , whitespaceLine ), nil
227
229
}
228
230
return nil , nil
@@ -231,30 +233,41 @@ func Completion(ctx context.Context, params *protocol.CompletionParams, manager
231
233
}
232
234
233
235
path , nodeProps , arrayAttributes := nodeProperties (path , line , character )
234
- dependencies := dependencyCompletionItems (file , documentPath , path , params , wordPrefix )
236
+ dependencies := dependencyCompletionItems (file , documentPath , path , params , prefixLength )
235
237
if len (dependencies ) > 0 {
236
238
return & protocol.CompletionList {Items : dependencies }, nil
237
239
}
238
- items , stop := buildTargetCompletionItems (params , manager , path , documentPath , wordPrefix )
240
+ items , stop := buildTargetCompletionItems (params , manager , path , documentPath , prefixLength )
239
241
if stop {
240
242
return & protocol.CompletionList {Items : items }, nil
241
243
}
244
+ folderStructureItems := folderStructureCompletionItems (documentPath , path , removeQuote (prefixContent ))
245
+ if len (folderStructureItems ) > 0 {
246
+ return processItems (folderStructureItems , whitespaceLine && arrayAttributes ), nil
247
+ }
242
248
243
- items = namedDependencyCompletionItems (file , path , "configs" , "configs" , params , wordPrefix )
249
+ items = namedDependencyCompletionItems (file , path , "configs" , "configs" , params , prefixLength )
244
250
if len (items ) == 0 {
245
- items = namedDependencyCompletionItems (file , path , "secrets" , "secrets" , params , wordPrefix )
251
+ items = namedDependencyCompletionItems (file , path , "secrets" , "secrets" , params , prefixLength )
246
252
}
247
253
if len (items ) == 0 {
248
- items = volumeDependencyCompletionItems (file , path , params , wordPrefix )
254
+ items = volumeDependencyCompletionItems (file , path , params , prefixLength )
249
255
}
250
- schemaItems := createSchemaItems (params , nodeProps , lines , lspLine , whitespaceLine && arrayAttributes , wordPrefix , file , manager , documentPath , path )
256
+ schemaItems := createSchemaItems (params , nodeProps , lines , lspLine , whitespaceLine && arrayAttributes , prefixLength , file , manager , documentPath , path )
251
257
items = append (items , schemaItems ... )
252
258
if len (items ) == 0 {
253
259
return nil , nil
254
260
}
255
261
return processItems (items , whitespaceLine && arrayAttributes ), nil
256
262
}
257
263
264
+ func removeQuote (prefix string ) string {
265
+ if len (prefix ) > 0 && (prefix [0 ] == 34 || prefix [0 ] == 39 ) {
266
+ return prefix [1 :]
267
+ }
268
+ return prefix
269
+ }
270
+
258
271
func createEnumItems (schema * jsonschema.Schema , params * protocol.CompletionParams , wordPrefixLength protocol.UInteger ) []protocol.CompletionItem {
259
272
items := []protocol.CompletionItem {}
260
273
for _ , value := range schema .Enum .Values {
@@ -382,6 +395,54 @@ func modifyTextEdit(file *ast.File, manager *document.Manager, documentPath docu
382
395
return edit
383
396
}
384
397
398
+ func folderStructureCompletionItems (documentPath document.DocumentPath , path []* ast.MappingValueNode , prefix string ) []protocol.CompletionItem {
399
+ folder := directoryForPrefix (documentPath , path , prefix )
400
+ if folder != "" {
401
+ items := []protocol.CompletionItem {}
402
+ entries , _ := os .ReadDir (folder )
403
+ for _ , entry := range entries {
404
+ item := protocol.CompletionItem {Label : entry .Name ()}
405
+ if entry .IsDir () {
406
+ item .Kind = types .CreateCompletionItemKindPointer (protocol .CompletionItemKindFolder )
407
+ } else {
408
+ item .Kind = types .CreateCompletionItemKindPointer (protocol .CompletionItemKindFile )
409
+ }
410
+ items = append (items , item )
411
+ }
412
+ return items
413
+ }
414
+ return nil
415
+ }
416
+
417
+ func directoryForPrefix (documentPath document.DocumentPath , path []* ast.MappingValueNode , prefix string ) string {
418
+ if len (path ) == 3 && path [2 ].Key .GetToken ().Value == "volumes" {
419
+ if strings .HasPrefix (prefix , "./" ) {
420
+ _ , folder := types .Concatenate (documentPath .Folder , prefix [0 :strings .LastIndex (prefix , "/" )], documentPath .WSLDollarSignHost )
421
+ return folder
422
+ }
423
+ } else if len (path ) == 4 && path [2 ].Key .GetToken ().Value == "volumes" && path [3 ].Key .GetToken ().Value == "source" {
424
+ if volumes , ok := path [2 ].Value .(* ast.SequenceNode ); ok {
425
+ for _ , node := range volumes .Values {
426
+ if volume , ok := node .(* ast.MappingNode ); ok {
427
+ if slices .Contains (volume .Values , path [3 ]) {
428
+ for _ , property := range volume .Values {
429
+ if property .Key .GetToken ().Value == "type" && property .Value .GetToken ().Value == "bind" {
430
+ if strings .HasPrefix (prefix , "./" ) {
431
+ _ , folder := types .Concatenate (documentPath .Folder , prefix [0 :strings .LastIndex (prefix , "/" )], documentPath .WSLDollarSignHost )
432
+ return folder
433
+ }
434
+ return documentPath .Folder
435
+ }
436
+ }
437
+ return ""
438
+ }
439
+ }
440
+ }
441
+ }
442
+ }
443
+ return ""
444
+ }
445
+
385
446
func findDependencies (file * ast.File , dependencyType string ) []string {
386
447
services := []string {}
387
448
for _ , documentNode := range file .Docs {
0 commit comments