From 67ff22b74b6f2848e9e1e698e5f9c963f1eb3b2b Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Tue, 12 Mar 2024 11:40:29 +0100 Subject: [PATCH 1/6] test: add test case for hover for panics for invalid namespaced function expressions --- decoder/hover_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/decoder/hover_test.go b/decoder/hover_test.go index 5e132953..f4c2771f 100644 --- a/decoder/hover_test.go +++ b/decoder/hover_test.go @@ -661,6 +661,34 @@ func TestDecoder_HoverAtPos_basic(t *testing.T) { } } +func TestDecoder_HoverAtPos_nil_expr(t *testing.T) { + // provider:: is not a traversal expression, so hcl will return a ExprSyntaxError which needs to be handled + f, _ := hclsyntax.ParseConfig([]byte(`attr = provider::`), "test.tf", hcl.InitialPos) + + d := testPathDecoder(t, &PathContext{ + Schema: &schema.BodySchema{ + Attributes: map[string]*schema.AttributeSchema{ + "attr": {Constraint: schema.AnyExpression{OfType: cty.DynamicPseudoType}}, + }, + }, + Files: map[string]*hcl.File{ + "test.tf": f, + }, + }) + + ctx := context.Background() + _, err := d.HoverAtPos(ctx, "test.tf", hcl.Pos{Line: 1, Column: 16, Byte: 15}) + + if err == nil { + t.Fatal("expected error") + } + + positionalErr := &PositionalError{} + if !errors.As(err, &positionalErr) { + t.Fatal("expected PositionalError for invalid expression") + } +} + func TestDecoder_HoverAtPos_URL(t *testing.T) { resourceLabelSchema := []*schema.LabelSchema{ {Name: "type", IsDepKey: true}, From 516cc9a5bcb1bb120912592e71cb1b179ea7c794 Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Tue, 12 Mar 2024 11:42:17 +0100 Subject: [PATCH 2/6] test: add test case for reference origins for panics for invalid namespaced function expressions --- decoder/reference_origins_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/decoder/reference_origins_test.go b/decoder/reference_origins_test.go index 6d5fd53b..81fb168e 100644 --- a/decoder/reference_origins_test.go +++ b/decoder/reference_origins_test.go @@ -11,7 +11,9 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/hcl-lang/lang" "github.com/hashicorp/hcl-lang/reference" + "github.com/hashicorp/hcl-lang/schema" "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/zclconf/go-cty-debug/ctydebug" "github.com/zclconf/go-cty/cty" ) @@ -763,3 +765,28 @@ func TestReferenceOriginsTargetingPos(t *testing.T) { }) } } + +func TestCollectReferenceOrigins_nil_expr(t *testing.T) { + // provider:: is not a traversal expression, so hcl will return a ExprSyntaxError which needs to be handled + f, _ := hclsyntax.ParseConfig([]byte(`attr = provider::`), "test.tf", hcl.InitialPos) + + d := testPathDecoder(t, &PathContext{ + Schema: &schema.BodySchema{ + Attributes: map[string]*schema.AttributeSchema{ + "attr": {Constraint: schema.AnyExpression{OfType: cty.DynamicPseudoType}}, + }, + }, + Files: map[string]*hcl.File{ + "test.tf": f, + }, + }) + + targets, err := d.CollectReferenceOrigins() + if err != nil { + t.Fatal("unexpected error when collecting reference origins while there was no expr in one of them") + } + + if len(targets) != 0 { + t.Fatalf("expected no targets, got %d", len(targets)) + } +} From 8b51bb7dcfc0ef880072f9bef70dfe8c898081cb Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Tue, 12 Mar 2024 11:43:42 +0100 Subject: [PATCH 3/6] test: add test case for semantic tokens for panics for invalid namespaced function expressions --- decoder/semantic_tokens_test.go | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/decoder/semantic_tokens_test.go b/decoder/semantic_tokens_test.go index 6a95d5f5..dd28cfba 100644 --- a/decoder/semantic_tokens_test.go +++ b/decoder/semantic_tokens_test.go @@ -320,6 +320,54 @@ resource "vault_auth_backend" "blah" { } } +func TestDecoder_SemanticTokensInFile_nil_expr(t *testing.T) { + // provider:: is not a traversal expression, so hcl will return a ExprSyntaxError which needs to be handled + f, _ := hclsyntax.ParseConfig([]byte(`attr = provider::`), "test.tf", hcl.InitialPos) + + d := testPathDecoder(t, &PathContext{ + Schema: &schema.BodySchema{ + Attributes: map[string]*schema.AttributeSchema{ + "attr": {Constraint: schema.AnyExpression{OfType: cty.DynamicPseudoType}}, + }, + }, + Files: map[string]*hcl.File{ + "test.tf": f, + }, + }) + + ctx := context.Background() + + tokens, err := d.SemanticTokensInFile(ctx, "test.tf") + if err != nil { + t.Fatal(err) + } + + expectedTokens := []lang.SemanticToken{ + { + Type: "hcl-attrName", + Modifiers: lang.SemanticTokenModifiers{}, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 1, + Byte: 0, + }, + End: hcl.Pos{ + Line: 1, + Column: 5, + Byte: 4, + }, + }, + }, + } + + diff := cmp.Diff(expectedTokens, tokens) + if diff != "" { + t.Fatalf("unexpected tokens: %s", diff) + } +} + func TestDecoder_SemanticTokensInFile_dependentSchema(t *testing.T) { bodySchema := &schema.BodySchema{ Blocks: map[string]*schema.BlockSchema{ From f05e0f159735c892644c64713e8810b844a4408e Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Tue, 12 Mar 2024 11:44:46 +0100 Subject: [PATCH 4/6] test: add test case for reference targets for panics for invalid namespaced function expressions --- decoder/reference_targets_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/decoder/reference_targets_test.go b/decoder/reference_targets_test.go index 07ffbecc..b727a0c3 100644 --- a/decoder/reference_targets_test.go +++ b/decoder/reference_targets_test.go @@ -12,7 +12,9 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/hcl-lang/lang" "github.com/hashicorp/hcl-lang/reference" + "github.com/hashicorp/hcl-lang/schema" "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/zclconf/go-cty-debug/ctydebug" "github.com/zclconf/go-cty/cty" ) @@ -352,3 +354,27 @@ func TestReferenceTargetForOriginAtPos(t *testing.T) { }) } } + +func TestCollectReferenceTargets_nil_expr(t *testing.T) { + // provider:: is not a traversal expression, so hcl will return a ExprSyntaxError which needs to be handled + f, _ := hclsyntax.ParseConfig([]byte(`attr = provider::`), "test.tf", hcl.InitialPos) + + d := testPathDecoder(t, &PathContext{ + Schema: &schema.BodySchema{ + Attributes: map[string]*schema.AttributeSchema{ + "attr": {Constraint: schema.AnyExpression{OfType: cty.DynamicPseudoType}}, + }, + }, + Files: map[string]*hcl.File{ + "test.tf": f, + }, + }) + targets, err := d.CollectReferenceTargets() + if err != nil { + t.Fatal("unexpected error when collecting reference targets while there was no expr in one of them") + } + + if len(targets) != 0 { + t.Fatalf("expected no targets, got %d", len(targets)) + } +} From 6fab43b3dbf2e2be0ad2e0dd4a302b0abf576707 Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Tue, 12 Mar 2024 11:47:15 +0100 Subject: [PATCH 5/6] test: add test case for completions for panics for invalid namespaced function expressions --- decoder/candidates_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/decoder/candidates_test.go b/decoder/candidates_test.go index 60ca4d37..3d5486dd 100644 --- a/decoder/candidates_test.go +++ b/decoder/candidates_test.go @@ -1325,6 +1325,39 @@ resource "random_resource" "test" { } } +func TestDecoder_CompletionAtPos_nil_expr(t *testing.T) { + ctx := context.Background() + + // provider:: is not a traversal expression, so hcl will return a ExprSyntaxError which needs to be handled + f, _ := hclsyntax.ParseConfig([]byte(`attr = provider::`), "test.tf", hcl.InitialPos) + + d := testPathDecoder(t, &PathContext{ + Schema: &schema.BodySchema{ + Attributes: map[string]*schema.AttributeSchema{ + "attr": {Constraint: schema.AnyExpression{OfType: cty.DynamicPseudoType}}, + }, + }, + Files: map[string]*hcl.File{ + "test.tf": f, + }, + }) + + pos := hcl.Pos{Line: 1, Column: 18, Byte: 17} + + candidates, err := d.CompletionAtPos(ctx, "test.tf", pos) + if err != nil { + t.Fatal(err) + } + + expectedCandidates := lang.CompleteCandidates([]lang.Candidate{}) + + diff := cmp.Diff(expectedCandidates, candidates, ctydebug.CmpOptions) + if diff != "" { + t.Fatalf("unexpected schema for %s: %s", stringPos(pos), diff) + } + +} + func TestDecoder_CompletionAtPos_AnyAttribute(t *testing.T) { ctx := context.Background() providersSchema := &schema.BlockSchema{ From a811b535473e0101239cafc552e0917c51f7fdaa Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Fri, 5 Apr 2024 14:15:56 +0200 Subject: [PATCH 6/6] fix test for hover data on invalid code --- decoder/hover_test.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/decoder/hover_test.go b/decoder/hover_test.go index f4c2771f..77c0f950 100644 --- a/decoder/hover_test.go +++ b/decoder/hover_test.go @@ -677,15 +677,14 @@ func TestDecoder_HoverAtPos_nil_expr(t *testing.T) { }) ctx := context.Background() - _, err := d.HoverAtPos(ctx, "test.tf", hcl.Pos{Line: 1, Column: 16, Byte: 15}) + hoverData, err := d.HoverAtPos(ctx, "test.tf", hcl.Pos{Line: 1, Column: 16, Byte: 15}) - if err == nil { - t.Fatal("expected error") + if err != nil { + t.Fatal(err) } - positionalErr := &PositionalError{} - if !errors.As(err, &positionalErr) { - t.Fatal("expected PositionalError for invalid expression") + if hoverData != nil { + t.Fatalf("expected nil hover data, got: %v", hoverData) } }