From e81bda33bd6bc8ce9bfa2aeed32154e31034e56e Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Fri, 11 Nov 2022 17:27:22 +0100 Subject: [PATCH] Refactor semanticTokensInFile to use collected origins --- decoder/semantic_tokens.go | 22 +++- decoder/semantic_tokens_expr_test.go | 155 +++++++++++++++++++++++++++ decoder/semantic_tokens_test.go | 66 ++++++++++++ 3 files changed, 238 insertions(+), 5 deletions(-) diff --git a/decoder/semantic_tokens.go b/decoder/semantic_tokens.go index 78d1e376..a9332ff2 100644 --- a/decoder/semantic_tokens.go +++ b/decoder/semantic_tokens.go @@ -195,16 +195,28 @@ func (d *PathDecoder) tokensForExpression(ctx context.Context, expr hclsyntax.Ex return tokens } - tes, ok := constraints.TraversalExprs() - if ok && d.pathCtx.ReferenceTargets != nil { + _, ok = constraints.TraversalExprs() + if ok && d.pathCtx.ReferenceTargets != nil && d.pathCtx.ReferenceOrigins != nil { traversal := eType.AsTraversal() - origin, err := reference.TraversalToLocalOrigin(traversal, tes) - if err != nil { + origins, ok := d.pathCtx.ReferenceOrigins.AtPos(traversal.SourceRange().Filename, traversal.SourceRange().Start) + if !ok { return tokens } - _, targetFound := d.pathCtx.ReferenceTargets.Match(origin) + targetFound := false + for _, origin := range origins { + matchableOrigin, ok := origin.(reference.MatchableOrigin) + if !ok { + continue + } + _, ok = d.pathCtx.ReferenceTargets.Match(matchableOrigin) + if ok { + targetFound = true + break + } + } + if !targetFound { return tokens } diff --git a/decoder/semantic_tokens_expr_test.go b/decoder/semantic_tokens_expr_test.go index cc0a4284..cf5c8146 100644 --- a/decoder/semantic_tokens_expr_test.go +++ b/decoder/semantic_tokens_expr_test.go @@ -1473,6 +1473,7 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { name string attrSchema map[string]*schema.AttributeSchema refs reference.Targets + origins reference.Origins cfg string expectedTokens []lang.SemanticToken }{ @@ -1486,6 +1487,27 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { }, }, reference.Targets{}, + reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "var"}, + lang.AttrStep{Name: "blah"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 7, + Byte: 6, + }, + End: hcl.Pos{ + Line: 1, + Column: 15, + Byte: 14, + }, + }, + }, + }, `attr = var.blah `, []lang.SemanticToken{ @@ -1526,6 +1548,32 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { Type: cty.Bool, }, }, + reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "var"}, + lang.AttrStep{Name: "blah"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 7, + Byte: 6, + }, + End: hcl.Pos{ + Line: 1, + Column: 15, + Byte: 14, + }, + }, + Constraints: reference.OriginConstraints{ + reference.OriginConstraint{ + OfType: cty.String, + }, + }, + }, + }, `attr = var.blah `, []lang.SemanticToken{ @@ -1566,6 +1614,32 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { Type: cty.String, }, }, + reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "var"}, + lang.AttrStep{Name: "blah"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 7, + Byte: 6, + }, + End: hcl.Pos{ + Line: 1, + Column: 15, + Byte: 14, + }, + }, + Constraints: reference.OriginConstraints{ + reference.OriginConstraint{ + OfType: cty.String, + }, + }, + }, + }, `attr = var.blah `, []lang.SemanticToken{ @@ -1640,6 +1714,32 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { ScopeId: lang.ScopeId("foo"), }, }, + reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "var"}, + lang.AttrStep{Name: "blah"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 7, + Byte: 6, + }, + End: hcl.Pos{ + Line: 1, + Column: 15, + Byte: 14, + }, + }, + Constraints: reference.OriginConstraints{ + reference.OriginConstraint{ + OfScopeId: lang.ScopeId("foo"), + }, + }, + }, + }, `attr = var.blah `, []lang.SemanticToken{ @@ -1716,6 +1816,33 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { }, }, }, + reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "var"}, + lang.AttrStep{Name: "foo"}, + lang.IndexStep{Key: cty.StringVal("test")}, + lang.AttrStep{Name: "bar"}, + lang.IndexStep{Key: cty.NumberIntVal(4)}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 7, + Byte: 6, + }, + End: hcl.Pos{ + Line: 1, + Column: 29, + Byte: 28, + }, + }, + Constraints: reference.OriginConstraints{ + reference.OriginConstraint{}, + }, + }, + }, `attr = var.foo["test"].bar[4] `, []lang.SemanticToken{ @@ -1841,6 +1968,33 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { Type: cty.DynamicPseudoType, }, }, + reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "var"}, + lang.AttrStep{Name: "foo"}, + lang.AttrStep{Name: "bar"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 7, + Byte: 6, + }, + End: hcl.Pos{ + Line: 1, + Column: 18, + Byte: 17, + }, + }, + Constraints: reference.OriginConstraints{ + reference.OriginConstraint{ + OfType: cty.String, + }, + }, + }, + }, `attr = var.foo.bar `, []lang.SemanticToken{ @@ -1932,6 +2086,7 @@ func TestDecoder_SemanticTokensInFile_traversalExpression(t *testing.T) { d := testPathDecoder(t, &PathContext{ Schema: bodySchema, ReferenceTargets: tc.refs, + ReferenceOrigins: tc.origins, Files: map[string]*hcl.File{ "test.tf": f, }, diff --git a/decoder/semantic_tokens_test.go b/decoder/semantic_tokens_test.go index d3a4ccc9..a3a550c1 100644 --- a/decoder/semantic_tokens_test.go +++ b/decoder/semantic_tokens_test.go @@ -902,6 +902,27 @@ resource "aws_instance" "app_server" { Description: lang.PlainText("The distinct index number (starting with 0) corresponding to the instance"), }, } + refOrigins := reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "count"}, + lang.AttrStep{Name: "index"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 4, + Column: 20, + Byte: 80, + }, + End: hcl.Pos{ + Line: 4, + Column: 31, + Byte: 91, + }, + }, + }, + } f, pDiags := hclsyntax.ParseConfig(testCfg, "test.tf", hcl.InitialPos) if len(pDiags) > 0 { @@ -914,6 +935,7 @@ resource "aws_instance" "app_server" { "test.tf": f, }, ReferenceTargets: refTargets, + ReferenceOrigins: refOrigins, }) ctx := context.Background() @@ -1130,6 +1152,27 @@ resource "aws_instance" "app_server" { Description: lang.PlainText("The distinct index number (starting with 0) corresponding to the instance"), }, } + refOrigins := reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "count"}, + lang.AttrStep{Name: "index"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 4, + Column: 20, + Byte: 80, + }, + End: hcl.Pos{ + Line: 4, + Column: 31, + Byte: 91, + }, + }, + }, + } f, pDiags := hclsyntax.ParseConfig(testCfg, "test.tf", hcl.InitialPos) if len(pDiags) > 0 { @@ -1142,6 +1185,7 @@ resource "aws_instance" "app_server" { "test.tf": f, }, ReferenceTargets: refTargets, + ReferenceOrigins: refOrigins, }) ctx := context.Background() @@ -1490,6 +1534,27 @@ resource "foobar" "name" { Description: lang.PlainText("The distinct index number (starting with 0) corresponding to the instance"), }, } + refOrigins := reference.Origins{ + reference.LocalOrigin{ + Addr: lang.Address{ + lang.RootStep{Name: "count"}, + lang.AttrStep{Name: "index"}, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 5, + Column: 10, + Byte: 57, + }, + End: hcl.Pos{ + Line: 5, + Column: 21, + Byte: 68, + }, + }, + }, + } f, pDiags := hclsyntax.ParseConfig(testCfg, "test.tf", hcl.InitialPos) if len(pDiags) > 0 { @@ -1502,6 +1567,7 @@ resource "foobar" "name" { "test.tf": f, }, ReferenceTargets: refTargets, + ReferenceOrigins: refOrigins, }) ctx := context.Background()