Skip to content

Commit f48e63d

Browse files
authored
Use local ref. targets for count.index (#160)
* Add RangePtr to body content * Use local ref. targets for count.index
1 parent 0f2e32b commit f48e63d

File tree

8 files changed

+83
-50
lines changed

8 files changed

+83
-50
lines changed

decoder/body_extensions_test.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func TestCompletionAtPos_BodySchema_Extensions(t *testing.T) {
6060
{
6161
Label: "count",
6262
Description: lang.MarkupContent{
63-
Value: "The distinct index number (starting with 0) corresponding to the instance",
63+
Value: "Total number of instances of this block.\n\n**Note**: A given block cannot use both `count` and `for_each`.",
6464
Kind: lang.MarkdownKind,
6565
},
6666
Detail: "optional, number",
@@ -136,7 +136,7 @@ func TestCompletionAtPos_BodySchema_Extensions(t *testing.T) {
136136
{
137137
Label: "count",
138138
Description: lang.MarkupContent{
139-
Value: "The distinct index number (starting with 0) corresponding to the instance",
139+
Value: "Total number of instances of this block.\n\n**Note**: A given block cannot use both `count` and `for_each`.",
140140
Kind: lang.MarkdownKind,
141141
},
142142
Detail: "optional, number",
@@ -289,7 +289,16 @@ func TestCompletionAtPos_BodySchema_Extensions(t *testing.T) {
289289
},
290290
},
291291
},
292-
reference.Targets{},
292+
reference.Targets{
293+
{
294+
LocalAddr: lang.Address{
295+
lang.RootStep{Name: "count"},
296+
lang.AttrStep{Name: "index"},
297+
},
298+
Type: cty.Number,
299+
Description: lang.PlainText("The distinct index number (starting with 0) corresponding to the instance"),
300+
},
301+
},
293302
`resource "aws_instance" "foo" {
294303
count = 4
295304
cpu_count =
@@ -440,7 +449,42 @@ func TestCompletionAtPos_BodySchema_Extensions(t *testing.T) {
440449
},
441450
},
442451
},
443-
reference.Targets{},
452+
reference.Targets{
453+
{
454+
LocalAddr: lang.Address{
455+
lang.RootStep{Name: "count"},
456+
lang.AttrStep{Name: "index"},
457+
},
458+
Type: cty.Number,
459+
Description: lang.PlainText("The distinct index number (starting with 0) corresponding to the instance"),
460+
RangePtr: &hcl.Range{
461+
Filename: "test.tf",
462+
Start: hcl.Pos{
463+
Line: 2,
464+
Column: 3,
465+
Byte: 34,
466+
},
467+
End: hcl.Pos{
468+
Line: 2,
469+
Column: 12,
470+
Byte: 43,
471+
},
472+
},
473+
DefRangePtr: &hcl.Range{
474+
Filename: "test.tf",
475+
Start: hcl.Pos{
476+
Line: 2,
477+
Column: 3,
478+
Byte: 34,
479+
},
480+
End: hcl.Pos{
481+
Line: 2,
482+
Column: 8,
483+
Byte: 39,
484+
},
485+
},
486+
},
487+
},
444488
`resource "aws_instance" "foo" {
445489
count = 4
446490
foo {

decoder/decoder.go

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/hashicorp/hcl-lang/lang"
7+
"github.com/hashicorp/hcl-lang/reference"
78
"github.com/hashicorp/hcl-lang/schema"
89
"github.com/hashicorp/hcl/v2"
910
"github.com/hashicorp/hcl/v2/hclsyntax"
@@ -104,6 +105,7 @@ type blockContent struct {
104105
type bodyContent struct {
105106
Attributes hcl.Attributes
106107
Blocks []*blockContent
108+
RangePtr *hcl.Range
107109
}
108110

109111
// decodeBody produces content of either HCL or JSON body
@@ -131,6 +133,8 @@ func decodeBody(body hcl.Body, bodySchema *schema.BodySchema) bodyContent {
131133
})
132134
}
133135

136+
content.RangePtr = hclBody.Range().Ptr()
137+
134138
return content
135139
}
136140

@@ -177,7 +181,8 @@ func countAttributeSchema() *schema.AttributeSchema {
177181
schema.TraversalExpr{OfType: cty.Number},
178182
schema.LiteralTypeExpr{Type: cty.Number},
179183
},
180-
Description: lang.Markdown("The distinct index number (starting with 0) corresponding to the instance"),
184+
Description: lang.Markdown("Total number of instances of this block.\n\n" +
185+
"**Note**: A given block cannot use both `count` and `for_each`."),
181186
}
182187
}
183188

@@ -245,24 +250,17 @@ func dynamicBlockSchema() *schema.BlockSchema {
245250
}
246251
}
247252

248-
func countIndexHoverData(rng hcl.Range) *lang.HoverData {
249-
return &lang.HoverData{
250-
Content: lang.Markdown("`count.index` _number_\n\nThe distinct index number (starting with 0) corresponding to the instance"),
251-
Range: rng,
252-
}
253-
}
254-
255-
func countIndexCandidate(editRng hcl.Range) lang.Candidate {
256-
return lang.Candidate{
257-
Label: "count.index",
258-
Detail: "number",
259-
Description: lang.PlainText("The distinct index number (starting with 0) corresponding to the instance"),
260-
Kind: lang.TraversalCandidateKind,
261-
TextEdit: lang.TextEdit{
262-
NewText: "count.index",
263-
Snippet: "count.index",
264-
Range: editRng,
253+
func countIndexReferenceTarget(attr *hcl.Attribute, bodyRange hcl.Range) reference.Target {
254+
return reference.Target{
255+
LocalAddr: lang.Address{
256+
lang.RootStep{Name: "count"},
257+
lang.AttrStep{Name: "index"},
265258
},
259+
TargetableFromRangePtr: bodyRange.Ptr(),
260+
Type: cty.Number,
261+
Description: lang.Markdown("The distinct index number (starting with 0) corresponding to the instance"),
262+
RangePtr: attr.Range.Ptr(),
263+
DefRangePtr: attr.NameRange.Ptr(),
266264
}
267265
}
268266

decoder/expression_candidates.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,6 @@ func (d *PathDecoder) constraintToCandidates(ctx context.Context, constraint sch
328328
},
329329
})
330330
case schema.TraversalExpr:
331-
if schema.ActiveCountFromContext(ctx) && attr.Name != "count" {
332-
candidates = append(candidates, countIndexCandidate(editRng))
333-
}
334331
if schema.ActiveForEachFromContext(ctx) && attr.Name != "for_each" {
335332
candidates = append(candidates, foreachEachCandidate(editRng)...)
336333
}

decoder/hover.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,10 @@ func (d *PathDecoder) hoverDataForExpr(ctx context.Context, expr hcl.Expression,
269269
return nil, err
270270
}
271271

272-
countIndexAddr := lang.Address{lang.RootStep{Name: "count"}, lang.AttrStep{Name: "index"}}
273272
eachKeyAddr := lang.Address{lang.RootStep{Name: "each"}, lang.AttrStep{Name: "key"}}
274273
eachValueAddr := lang.Address{lang.RootStep{Name: "each"}, lang.AttrStep{Name: "value"}}
275274

276-
if address.Equals(countIndexAddr) && schema.ActiveCountFromContext(ctx) {
277-
return countIndexHoverData(expr.Range()), nil
278-
} else if address.Equals(eachKeyAddr) && schema.ActiveForEachFromContext(ctx) {
275+
if address.Equals(eachKeyAddr) && schema.ActiveForEachFromContext(ctx) {
279276
return eachKeyHoverData(expr.Range()), nil
280277
} else if address.Equals(eachValueAddr) && schema.ActiveForEachFromContext(ctx) {
281278
return eachValueHoverData(expr.Range()), nil

decoder/hover_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@ func TestDecoder_HoverAtPos_extension(t *testing.T) {
970970
`,
971971
hcl.Pos{Line: 2, Column: 5, Byte: 24},
972972
&lang.HoverData{
973-
Content: lang.Markdown("**count** _optional, number_\n\nThe distinct index number (starting with 0) corresponding to the instance"),
973+
Content: lang.Markdown("**count** _optional, number_\n\nTotal number of instances of this block.\n\n**Note**: A given block cannot use both `count` and `for_each`."),
974974
Range: hcl.Range{
975975
Filename: "test.tf",
976976
Start: hcl.Pos{Line: 2, Column: 3, Byte: 24},
@@ -1034,7 +1034,7 @@ func TestDecoder_HoverAtPos_extension(t *testing.T) {
10341034
`,
10351035
hcl.Pos{Line: 3, Column: 15, Byte: 48},
10361036
&lang.HoverData{
1037-
Content: lang.Markdown("`count.index` _number_\n\nThe distinct index number (starting with 0) corresponding to the instance"),
1037+
Content: lang.Markdown("`count.index`\n_number_\n\nThe distinct index number (starting with 0) corresponding to the instance"),
10381038
Range: hcl.Range{
10391039
Filename: "test.tf",
10401040
Start: hcl.Pos{Line: 3, Column: 11, Byte: 44},

decoder/reference_targets.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ func (d *PathDecoder) decodeReferenceTargetsForBody(body hcl.Body, parentBlock *
107107
content := decodeBody(body, bodySchema)
108108

109109
for _, attr := range content.Attributes {
110+
if bodySchema.Extensions != nil {
111+
if bodySchema.Extensions.Count && attr.Name == "count" && content.RangePtr != nil {
112+
refs = append(refs, countIndexReferenceTarget(attr, *content.RangePtr))
113+
continue
114+
}
115+
}
110116
attrSchema, ok := bodySchema.Attributes[attr.Name]
111117
if !ok {
112118
if bodySchema.AnyAttribute == nil {

decoder/semantic_tokens.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,17 +187,6 @@ func (d *PathDecoder) tokensForExpression(ctx context.Context, expr hclsyntax.Ex
187187
return tokens
188188
}
189189

190-
countAvailable := schema.ActiveCountFromContext(ctx)
191-
countIndexAttr := lang.Address{
192-
lang.RootStep{Name: "count"}, lang.AttrStep{Name: "index"},
193-
}
194-
195-
if address.Equals(countIndexAttr) && countAvailable {
196-
tokens = append(tokens, semanticTokensForTraversalExpression(eType.AsTraversal())...)
197-
198-
return tokens
199-
}
200-
201190
foreachAvailable := schema.ActiveForEachFromContext(ctx)
202191
eachKeyAddress := lang.Address{
203192
lang.RootStep{Name: "each"}, lang.AttrStep{Name: "key"},

decoder/semantic_tokens_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ resource "vault_auth_backend" "blah" {
853853
}
854854
}
855855

856-
func TestDecoder_SemanticTokensInFile_extensions(t *testing.T) {
856+
func TestDecoder_SemanticTokensInFile_extensions_basic(t *testing.T) {
857857
bodySchema := &schema.BodySchema{
858858
Blocks: map[string]*schema.BlockSchema{
859859
"resource": {
@@ -1079,8 +1079,8 @@ resource "aws_instance" "app_server" {
10791079
},
10801080
End: hcl.Pos{
10811081
Line: 4,
1082-
Column: 32,
1083-
Byte: 92,
1082+
Column: 31,
1083+
Byte: 91,
10841084
},
10851085
},
10861086
},
@@ -1329,8 +1329,8 @@ resource "aws_instance" "app_server" {
13291329
},
13301330
End: hcl.Pos{
13311331
Line: 4,
1332-
Column: 32,
1333-
Byte: 92,
1332+
Column: 31,
1333+
Byte: 91,
13341334
},
13351335
},
13361336
},
@@ -1492,7 +1492,9 @@ func TestDecoder_SemanticTokensInFile_extensions_countIndexInSubBlock(t *testing
14921492
Body: &schema.BodySchema{
14931493
Attributes: map[string]*schema.AttributeSchema{
14941494
"attr": {
1495-
Expr: schema.LiteralTypeOnly(cty.Number),
1495+
Expr: schema.ExprConstraints{
1496+
schema.TraversalExpr{OfType: cty.Number},
1497+
},
14961498
},
14971499
},
14981500
},
@@ -1726,8 +1728,8 @@ resource "foobar" "name" {
17261728
},
17271729
End: hcl.Pos{
17281730
Line: 5,
1729-
Column: 22,
1730-
Byte: 69,
1731+
Column: 21,
1732+
Byte: 68,
17311733
},
17321734
},
17331735
},

0 commit comments

Comments
 (0)