From 59b41cf8f779022efebe3c59db33c7fc02f74c5e Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Fri, 25 Nov 2022 18:02:40 +0100 Subject: [PATCH 1/3] Add test case for label completion --- decoder/body_extensions_test.go | 72 ++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/decoder/body_extensions_test.go b/decoder/body_extensions_test.go index 0ed1e2f6..7e2c2efe 100644 --- a/decoder/body_extensions_test.go +++ b/decoder/body_extensions_test.go @@ -1695,6 +1695,7 @@ func TestCompletionAtPos_BodySchema_Extensions_DynamicBlock(t *testing.T) { cfg string pos hcl.Pos expectedCandidates lang.Candidates + expectedErr string }{ { "dynamic block does not complete if not enabled", @@ -1728,6 +1729,7 @@ resource "aws_elastic_beanstalk_environment" "example" { Byte: 77, }, lang.CompleteCandidates([]lang.Candidate{}), + "", }, { "dynamic block does not complete without blocks", @@ -1783,6 +1785,7 @@ resource "aws_elastic_beanstalk_environment" "example" { Kind: lang.AttributeCandidateKind, }, }), + "", }, { "dynamic block completion", @@ -1878,6 +1881,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, { "dynamic block inner completion", @@ -2001,6 +2005,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, { "dynamic block content attribute completion", @@ -2074,6 +2079,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, { "dynamic block label only completes dependent blocks", @@ -2136,6 +2142,52 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", + }, + { + "dynamic block label never completes static blocks", + &schema.BodySchema{ + Blocks: map[string]*schema.BlockSchema{ + "resource": { + Labels: []*schema.LabelSchema{ + { + Name: "type", + IsDepKey: true, + Completable: true, + }, + {Name: "name"}, + }, + Body: &schema.BodySchema{ + Extensions: &schema.BodyExtensions{ + DynamicBlocks: true, + }, + Blocks: map[string]*schema.BlockSchema{ + "lifecycle": { + Body: schema.NewBodySchema(), + }, + }, + }, + DependentBody: map[schema.SchemaKey]*schema.BodySchema{ + schema.NewSchemaKey(schema.DependencyKeys{ + Labels: []schema.LabelDependent{ + {Index: 0, Value: "aws_instance"}, + }, + }): { + Blocks: make(map[string]*schema.BlockSchema, 0), + }, + }, + }, + }, + }, + `resource "aws_instance" "example" { + name = "example" + dynamic "" { + + } +}`, + hcl.Pos{Line: 3, Column: 12, Byte: 66}, + lang.CompleteCandidates([]lang.Candidate{}), + `test.tf (3,12): unknown block type "dynamic"`, }, // completion nesting should work { @@ -2245,6 +2297,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, // completion after the thing = { @@ -2333,6 +2386,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, // check allows more than one dynamic { @@ -2409,6 +2463,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, // allows dynamic blocks in blocks { @@ -2496,6 +2551,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, // never complete dynamic as a dynamic label { @@ -2562,6 +2618,7 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }, }), + "", }, } @@ -2576,14 +2633,17 @@ resource "aws_elastic_beanstalk_environment" "example" { }, }) - // We're triggering completion twice her, to cover any unintended side effects - _, err := d.CandidatesAtPos(ctx, "test.tf", tc.pos) - if err != nil { - t.Fatal(err) - } candidates, err := d.CandidatesAtPos(ctx, "test.tf", tc.pos) + if err != nil { - t.Fatal(err) + if tc.expectedErr != "" && err.Error() != tc.expectedErr { + t.Fatalf("unexpected error: %q\nexpected: %q\n", + err, tc.expectedErr) + } else if tc.expectedErr == "" { + t.Fatal(err) + } + } else if tc.expectedErr != "" { + t.Fatalf("expected error: %q", tc.expectedErr) } if diff := cmp.Diff(tc.expectedCandidates, candidates); diff != "" { From ed6bd921d8608097f5b399cf0990b7c3dc24b371 Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Tue, 29 Nov 2022 16:32:07 +0100 Subject: [PATCH 2/3] Only check block length if there is no dependent body --- decoder/decoder.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/decoder/decoder.go b/decoder/decoder.go index 9665330c..6366b1e0 100644 --- a/decoder/decoder.go +++ b/decoder/decoder.go @@ -50,10 +50,6 @@ func mergeBlockBodySchemas(block *hcl.Block, blockSchema *schema.BlockSchema) (* mergedSchema.ImpliedOrigins = make([]schema.ImpliedOrigin, 0) } - if mergedSchema.Extensions != nil && mergedSchema.Extensions.DynamicBlocks && len(mergedSchema.Blocks) > 0 { - mergedSchema.Blocks["dynamic"] = buildDynamicBlockSchema(mergedSchema) - } - depSchema, _, ok := NewBlockSchema(blockSchema).DependentBodySchema(block) if ok { for name, attr := range depSchema.Attributes { @@ -97,6 +93,10 @@ func mergeBlockBodySchemas(block *hcl.Block, blockSchema *schema.BlockSchema) (* if depSchema.Extensions != nil { mergedSchema.Extensions = depSchema.Extensions.Copy() } + } else { + if mergedSchema.Extensions != nil && mergedSchema.Extensions.DynamicBlocks && len(mergedSchema.Blocks) > 0 { + mergedSchema.Blocks["dynamic"] = buildDynamicBlockSchema(mergedSchema) + } } return mergedSchema, nil From 232fbe2d7077ec72fcdc8077f92594a0a41805c9 Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Wed, 30 Nov 2022 10:35:19 +0100 Subject: [PATCH 3/3] Turn else into else if --- decoder/decoder.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/decoder/decoder.go b/decoder/decoder.go index 6366b1e0..0c7685db 100644 --- a/decoder/decoder.go +++ b/decoder/decoder.go @@ -93,10 +93,8 @@ func mergeBlockBodySchemas(block *hcl.Block, blockSchema *schema.BlockSchema) (* if depSchema.Extensions != nil { mergedSchema.Extensions = depSchema.Extensions.Copy() } - } else { - if mergedSchema.Extensions != nil && mergedSchema.Extensions.DynamicBlocks && len(mergedSchema.Blocks) > 0 { - mergedSchema.Blocks["dynamic"] = buildDynamicBlockSchema(mergedSchema) - } + } else if !ok && mergedSchema.Extensions != nil && mergedSchema.Extensions.DynamicBlocks && len(mergedSchema.Blocks) > 0 { + mergedSchema.Blocks["dynamic"] = buildDynamicBlockSchema(mergedSchema) } return mergedSchema, nil