From 34220ff13ee8e6806ccfd7f23900725cc65c75c2 Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Thu, 14 Aug 2025 08:43:07 -0400 Subject: [PATCH] Support folder completions for the contexts attribute Signed-off-by: Remy Suen --- CHANGELOG.md | 1 + internal/bake/hcl/completion.go | 21 ++++++++++++++++----- internal/bake/hcl/completion_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d9aac..4507b44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the Docker Language Server will be documented in this fil - textDocument/completion - provide local file and folder name suggestions ([#414](https://github.com/docker/docker-language-server/issues/414)) - `context` attribute in a `target` block + - `contexts` attribute in a `target` block - `dockerfile` attribute in a `target` block ### Fixed diff --git a/internal/bake/hcl/completion.go b/internal/bake/hcl/completion.go index f57d7cf..94500af 100644 --- a/internal/bake/hcl/completion.go +++ b/internal/bake/hcl/completion.go @@ -70,11 +70,22 @@ func Completion(ctx context.Context, params *protocol.CompletionParams, manager } if attribute, ok := attributes["dockerfile"]; ok && isInsideRange(attribute.Expr.Range(), params.Position) { - return fileStructureCompletionItems(bakeDocument, attribute, params.Position.Character, false) + return fileStructureCompletionItems(bakeDocument, attribute.Expr, params.Position.Character, false) } if attribute, ok := attributes["context"]; ok && isInsideRange(attribute.Expr.Range(), params.Position) { - return fileStructureCompletionItems(bakeDocument, attribute, params.Position.Character, true) + return fileStructureCompletionItems(bakeDocument, attribute.Expr, params.Position.Character, true) + } + + if attribute, ok := attributes["contexts"]; ok && isInsideRange(attribute.Expr.Range(), params.Position) { + if expr, ok := attribute.Expr.(*hclsyntax.ObjectConsExpr); ok { + for _, item := range expr.Items { + if isInsideRange(item.ValueExpr.Range(), params.Position) { + return fileStructureCompletionItems(bakeDocument, item.ValueExpr, params.Position.Character, true) + } + } + } + return nil, nil } dockerfileURI, dockerfilePath, err := bakeDocument.DockerfileForTarget(b) @@ -166,9 +177,9 @@ func Completion(ctx context.Context, params *protocol.CompletionParams, manager return list, nil } -func fileStructureCompletionItems(bakeDocument document.BakeHCLDocument, attribute *hclsyntax.Attribute, character protocol.UInteger, hideFiles bool) (*protocol.CompletionList, error) { - if expr, ok := attribute.Expr.(*hclsyntax.TemplateExpr); ok && len(expr.Parts) == 1 { - if literal, ok := expr.Parts[0].(*hclsyntax.LiteralValueExpr); ok { +func fileStructureCompletionItems(bakeDocument document.BakeHCLDocument, expression hclsyntax.Expression, character protocol.UInteger, hideFiles bool) (*protocol.CompletionList, error) { + if templateExpr, ok := expression.(*hclsyntax.TemplateExpr); ok && len(templateExpr.Parts) == 1 { + if literal, ok := templateExpr.Parts[0].(*hclsyntax.LiteralValueExpr); ok { path, err := bakeDocument.DocumentPath() if err == nil { value, _ := literal.Value(&hcl.EvalContext{}) diff --git a/internal/bake/hcl/completion_test.go b/internal/bake/hcl/completion_test.go index 4b78a20..f87d60e 100644 --- a/internal/bake/hcl/completion_test.go +++ b/internal/bake/hcl/completion_test.go @@ -443,6 +443,31 @@ target t1 { line: 2, character: 12, }, + { + name: "contexts attribute in a target block", + content: ` +target t1 { + contexts = { + src = "%v" + } +}`, + hideFiles: true, + line: 3, + character: 9, + }, + { + name: "contexts attribute in a target block with multiple contexts", + content: ` +target t1 { + contexts = { + src = "../path/to/source" + src2 = "%v" + } +}`, + hideFiles: true, + line: 4, + character: 10, + }, } setups := []struct {