Skip to content

Commit 30b1dc7

Browse files
committed
Implement file structure code completion for other simple string attributes
Signed-off-by: Remy Suen <[email protected]>
1 parent 6e14d3a commit 30b1dc7

File tree

3 files changed

+420
-34
lines changed

3 files changed

+420
-34
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ All notable changes to the Docker Language Server will be documented in this fil
1010
- textDocument/completion
1111
- provide local file and folder name suggestions when modifying simple strings
1212
- service volumes ([#376](https://github.com/docker/docker-language-server/issues/376))
13-
- env_file and label_file attributes of a service ([#403](https://github.com/docker/docker-language-server/issues/403))
13+
- `env_file` of a service ([#403](https://github.com/docker/docker-language-server/issues/403))
14+
- `label_file` of a service ([#403](https://github.com/docker/docker-language-server/issues/403))
15+
- `dockerfile` attribute of a `build` object of a service ([#403](https://github.com/docker/docker-language-server/issues/403))
16+
- `file` attribute of a `credential_spec` object of a service ([#403](https://github.com/docker/docker-language-server/issues/403))
17+
- `file` attribute of an `extends` object of a service ([#403](https://github.com/docker/docker-language-server/issues/403))
18+
- `file` attribute of a config ([#403](https://github.com/docker/docker-language-server/issues/403))
19+
- `file` attribute of a secret ([#403](https://github.com/docker/docker-language-server/issues/403))
1420

1521
### Fixed
1622

internal/compose/completion.go

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ func modifyTextEdit(file *ast.File, manager *document.Manager, documentPath docu
396396
}
397397

398398
func folderStructureCompletionItems(documentPath document.DocumentPath, path []*ast.MappingValueNode, prefix string) []protocol.CompletionItem {
399-
folder := directoryForPrefix(documentPath, path, prefix)
399+
folder := directoryForNode(documentPath, path, prefix)
400400
if folder != "" {
401401
items := []protocol.CompletionItem{}
402402
entries, _ := os.ReadDir(folder)
@@ -414,45 +414,69 @@ func folderStructureCompletionItems(documentPath document.DocumentPath, path []*
414414
return nil
415415
}
416416

417-
func directoryForPrefix(documentPath document.DocumentPath, path []*ast.MappingValueNode, prefix string) string {
418-
if len(path) == 3 && path[0].Key.GetToken().Value == "services" {
419-
if path[2].Key.GetToken().Value == "env_file" {
420-
idx := strings.LastIndex(prefix, "/")
421-
if idx == -1 {
422-
return documentPath.Folder
417+
func directoryForNode(documentPath document.DocumentPath, path []*ast.MappingValueNode, prefix string) string {
418+
if len(path) == 3 {
419+
switch path[0].Key.GetToken().Value {
420+
case "services":
421+
// services:
422+
// serviceA:
423+
// env_file: ...
424+
// label_file: ...
425+
// volumes:
426+
// - ...
427+
switch path[2].Key.GetToken().Value {
428+
case "env_file":
429+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, false)
430+
case "label_file":
431+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, false)
432+
case "volumes":
433+
return directoryForPrefix(documentPath, prefix, "", true)
423434
}
424-
_, folder := types.Concatenate(documentPath.Folder, prefix[0:idx], documentPath.WSLDollarSignHost)
425-
return folder
426-
}
427-
if path[2].Key.GetToken().Value == "label_file" {
428-
idx := strings.LastIndex(prefix, "/")
429-
if idx == -1 {
430-
return documentPath.Folder
435+
case "configs":
436+
// configs:
437+
// configA:
438+
// file: ...
439+
if path[2].Key.GetToken().Value == "file" {
440+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, false)
431441
}
432-
_, folder := types.Concatenate(documentPath.Folder, prefix[0:idx], documentPath.WSLDollarSignHost)
433-
return folder
434-
}
435-
if path[2].Key.GetToken().Value == "volumes" {
436-
if strings.HasPrefix(prefix, "./") {
437-
_, folder := types.Concatenate(documentPath.Folder, prefix[0:strings.LastIndex(prefix, "/")], documentPath.WSLDollarSignHost)
438-
return folder
442+
case "secrets":
443+
// secrets:
444+
// secretA:
445+
// file: ...
446+
if path[2].Key.GetToken().Value == "file" {
447+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, false)
439448
}
440449
}
441-
} else if len(path) == 4 && path[0].Key.GetToken().Value == "services" && path[2].Key.GetToken().Value == "volumes" && path[3].Key.GetToken().Value == "source" {
442-
if volumes, ok := path[2].Value.(*ast.SequenceNode); ok {
443-
for _, node := range volumes.Values {
444-
if volume, ok := node.(*ast.MappingNode); ok {
445-
if slices.Contains(volume.Values, path[3]) {
446-
for _, property := range volume.Values {
447-
if property.Key.GetToken().Value == "type" && property.Value.GetToken().Value == "bind" {
448-
if strings.HasPrefix(prefix, "./") {
449-
_, folder := types.Concatenate(documentPath.Folder, prefix[0:strings.LastIndex(prefix, "/")], documentPath.WSLDollarSignHost)
450-
return folder
450+
} else if len(path) == 4 && path[0].Key.GetToken().Value == "services" {
451+
// services:
452+
// serviceA:
453+
// build:
454+
// dockerfile: ...
455+
// credential_spec:
456+
// file: ...
457+
// extends:
458+
// file: ...
459+
// volumes:
460+
// - type: bind
461+
// source: ...
462+
if path[2].Key.GetToken().Value == "build" && path[3].Key.GetToken().Value == "dockerfile" {
463+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, false)
464+
}
465+
if (path[2].Key.GetToken().Value == "extends" || path[2].Key.GetToken().Value == "credential_spec") && path[3].Key.GetToken().Value == "file" {
466+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, false)
467+
}
468+
if path[2].Key.GetToken().Value == "volumes" && path[3].Key.GetToken().Value == "source" {
469+
if volumes, ok := path[2].Value.(*ast.SequenceNode); ok {
470+
for _, node := range volumes.Values {
471+
if volume, ok := node.(*ast.MappingNode); ok {
472+
if slices.Contains(volume.Values, path[3]) {
473+
for _, property := range volume.Values {
474+
if property.Key.GetToken().Value == "type" && property.Value.GetToken().Value == "bind" {
475+
return directoryForPrefix(documentPath, prefix, documentPath.Folder, true)
451476
}
452-
return documentPath.Folder
453477
}
478+
return ""
454479
}
455-
return ""
456480
}
457481
}
458482
}
@@ -461,6 +485,18 @@ func directoryForPrefix(documentPath document.DocumentPath, path []*ast.MappingV
461485
return ""
462486
}
463487

488+
func directoryForPrefix(documentPath document.DocumentPath, prefix, defaultValue string, prefixRequired bool) string {
489+
idx := strings.LastIndex(prefix, "/")
490+
if idx == -1 {
491+
if prefixRequired {
492+
return defaultValue
493+
}
494+
return documentPath.Folder
495+
}
496+
_, folder := types.Concatenate(documentPath.Folder, prefix[0:idx], documentPath.WSLDollarSignHost)
497+
return folder
498+
}
499+
464500
func findDependencies(file *ast.File, dependencyType string) []string {
465501
services := []string{}
466502
for _, documentNode := range file.Docs {

0 commit comments

Comments
 (0)