diff --git a/CHANGELOG.md b/CHANGELOG.md index 8127a31..6cc8c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to the Docker Language Server will be documented in this fil - Compose - textDocument/documentLink - return document links for files referenced in the short-form `volumes` attribute of a service object ([#460](https://github.com/docker/docker-language-server/issues/460)) + - return document links for files referenced in the long-form `volumes` attribute of a service object that has a bind mount ([#462](https://github.com/docker/docker-language-server/issues/462)) ## [0.18.0] - 2025-08-25 diff --git a/internal/compose/documentLink.go b/internal/compose/documentLink.go index 7d85f98..e3792ec 100644 --- a/internal/compose/documentLink.go +++ b/internal/compose/documentLink.go @@ -127,6 +127,32 @@ func createVolumeFileLinks(folderAbsolutePath string, wslDollarSign bool, servic }) } } + } else if m, ok := resolveAnchor(node).(*ast.MappingNode); ok { + bindType := false + for _, value := range m.Values { + if resolveAnchor(value.Key).GetToken().Value == "type" && resolveAnchor(value.Value).GetToken().Value == "bind" { + bindType = true + break + } + } + + if bindType { + for _, value := range m.Values { + if resolveAnchor(value.Key).GetToken().Value == "source" { + sourceToken := resolveAnchor(value.Value).GetToken() + uri, path := createLocalFileLink(folderAbsolutePath, sourceToken.Value, wslDollarSign) + info, err := os.Stat(path) + if err == nil && !info.IsDir() { + links = append(links, protocol.DocumentLink{ + Range: createRange(sourceToken, len(sourceToken.Value)), + Target: types.CreateStringPointer(uri), + Tooltip: types.CreateStringPointer(path), + }) + } + break + } + } + } } } return links diff --git a/internal/compose/documentLink_test.go b/internal/compose/documentLink_test.go index 1a35661..a8ce8fb 100644 --- a/internal/compose/documentLink_test.go +++ b/internal/compose/documentLink_test.go @@ -2125,6 +2125,91 @@ services: End: protocol.Position{Line: 4, Character: protocol.UInteger(8 + len(tempFile))}, }, }, + { + name: "mount local file with a complex volume object", + content: ` +services: + test: + volumes: + - type: bind + source: ./a.txt + target: /mnt/a.txt`, + path: filepath.Join(testsFolder, "./a.txt"), + linkRange: protocol.Range{ + Start: protocol.Position{Line: 5, Character: 16}, + End: protocol.Position{Line: 5, Character: 23}, + }, + }, + { + name: "mount local file with a complex volume object with the type's attribute name anchored", + content: ` +services: + test: + volumes: + - &anchor type: bind + source: ./a.txt + target: /mnt/a.txt`, + path: filepath.Join(testsFolder, "./a.txt"), + linkRange: protocol.Range{ + Start: protocol.Position{Line: 5, Character: 16}, + End: protocol.Position{Line: 5, Character: 23}, + }, + }, + { + name: "mount local file with a complex volume object with the type's attribute value anchored", + content: ` +services: + test: + volumes: + - type: &anchor bind + source: ./a.txt + target: /mnt/a.txt`, + path: filepath.Join(testsFolder, "./a.txt"), + linkRange: protocol.Range{ + Start: protocol.Position{Line: 5, Character: 16}, + End: protocol.Position{Line: 5, Character: 23}, + }, + }, + { + name: "mount local file with a complex volume object with the source's attribute name anchored", + content: ` +services: + test: + volumes: + - type: bind + &anchor source: ./a.txt + target: /mnt/a.txt`, + path: filepath.Join(testsFolder, "./a.txt"), + linkRange: protocol.Range{ + Start: protocol.Position{Line: 5, Character: 24}, + End: protocol.Position{Line: 5, Character: 31}, + }, + }, + { + name: "mount local file with a complex volume object with the source's attribute value anchored", + content: ` +services: + test: + volumes: + - type: bind + source: &anchor ./a.txt + target: /mnt/a.txt`, + path: filepath.Join(testsFolder, "./a.txt"), + linkRange: protocol.Range{ + Start: protocol.Position{Line: 5, Character: 24}, + End: protocol.Position{Line: 5, Character: 31}, + }, + }, + { + name: "mount local folder with a complex volume object", + content: ` +services: + test: + volumes: + - type: bind + source: ./folder + target: /mount/folder`, + }, } for _, tc := range testCases {