1
1
package decoder
2
2
3
3
import (
4
+ "context"
4
5
"sort"
5
6
7
+ "github.com/zclconf/go-cty/cty"
8
+
9
+ icontext "github.com/hashicorp/hcl-lang/context"
6
10
"github.com/hashicorp/hcl-lang/lang"
7
11
"github.com/hashicorp/hcl-lang/reference"
8
12
"github.com/hashicorp/hcl-lang/schema"
9
13
"github.com/hashicorp/hcl/v2"
10
14
"github.com/hashicorp/hcl/v2/hclsyntax"
11
- "github.com/zclconf/go-cty/cty"
12
15
)
13
16
14
17
// SemanticTokensInFile returns a sequence of semantic tokens
15
18
// within the config file.
16
- func (d * PathDecoder ) SemanticTokensInFile (filename string ) ([]lang.SemanticToken , error ) {
19
+ func (d * PathDecoder ) SemanticTokensInFile (ctx context. Context , filename string ) ([]lang.SemanticToken , error ) {
17
20
f , err := d .fileByName (filename )
18
21
if err != nil {
19
22
return nil , err
@@ -28,7 +31,7 @@ func (d *PathDecoder) SemanticTokensInFile(filename string) ([]lang.SemanticToke
28
31
return []lang.SemanticToken {}, nil
29
32
}
30
33
31
- tokens := d .tokensForBody (body , d .pathCtx .Schema , []lang.SemanticTokenModifier {})
34
+ tokens := d .tokensForBody (ctx , body , d .pathCtx .Schema , []lang.SemanticTokenModifier {})
32
35
33
36
sort .Slice (tokens , func (i , j int ) bool {
34
37
return tokens [i ].Range .Start .Byte < tokens [j ].Range .Start .Byte
@@ -37,21 +40,43 @@ func (d *PathDecoder) SemanticTokensInFile(filename string) ([]lang.SemanticToke
37
40
return tokens , nil
38
41
}
39
42
40
- func (d * PathDecoder ) tokensForBody (body * hclsyntax.Body , bodySchema * schema.BodySchema , parentModifiers []lang.SemanticTokenModifier ) []lang.SemanticToken {
43
+ func (d * PathDecoder ) tokensForBody (ctx context. Context , body * hclsyntax.Body , bodySchema * schema.BodySchema , parentModifiers []lang.SemanticTokenModifier ) []lang.SemanticToken {
41
44
tokens := make ([]lang.SemanticToken , 0 )
42
45
43
46
if bodySchema == nil {
44
47
return tokens
45
48
}
46
49
50
+ if bodySchema .Extensions != nil {
51
+ ctx = icontext .WithExtensions (ctx , bodySchema .Extensions )
52
+ if bodySchema .Extensions .Count {
53
+ if _ , ok := body .Attributes ["count" ]; ok {
54
+ // append to context we need count provided
55
+ ctx = icontext .WithActiveCount (ctx )
56
+ }
57
+ }
58
+ }
59
+
47
60
for name , attr := range body .Attributes {
61
+
48
62
attrSchema , ok := bodySchema .Attributes [name ]
49
63
if ! ok {
50
- if bodySchema .AnyAttribute == nil {
51
- // unknown attribute
52
- continue
64
+ if bodySchema .Extensions != nil && name == "count" && bodySchema .Extensions .Count {
65
+ attrSchema = & schema.AttributeSchema {
66
+ Description : lang.MarkupContent {
67
+ Kind : lang .MarkdownKind ,
68
+ Value : "**count** _optional, number_\n \n The distinct index number (starting with 0) corresponding to the instance" ,
69
+ },
70
+ IsOptional : true ,
71
+ Expr : schema .LiteralTypeOnly (cty .Number ),
72
+ }
73
+ } else {
74
+ if bodySchema .AnyAttribute == nil {
75
+ // unknown attribute
76
+ continue
77
+ }
78
+ attrSchema = bodySchema .AnyAttribute
53
79
}
54
- attrSchema = bodySchema .AnyAttribute
55
80
}
56
81
57
82
attrModifiers := make ([]lang.SemanticTokenModifier , 0 )
@@ -65,7 +90,7 @@ func (d *PathDecoder) tokensForBody(body *hclsyntax.Body, bodySchema *schema.Bod
65
90
})
66
91
67
92
ec := ExprConstraints (attrSchema .Expr )
68
- tokens = append (tokens , d .tokensForExpression (attr .Expr , ec )... )
93
+ tokens = append (tokens , d .tokensForExpression (ctx , attr .Expr , ec )... )
69
94
}
70
95
71
96
for _ , block := range body .Blocks {
@@ -106,19 +131,19 @@ func (d *PathDecoder) tokensForBody(body *hclsyntax.Body, bodySchema *schema.Bod
106
131
}
107
132
108
133
if block .Body != nil {
109
- tokens = append (tokens , d .tokensForBody (block .Body , blockSchema .Body , blockModifiers )... )
134
+ tokens = append (tokens , d .tokensForBody (ctx , block .Body , blockSchema .Body , blockModifiers )... )
110
135
}
111
136
112
137
depSchema , _ , ok := NewBlockSchema (blockSchema ).DependentBodySchema (block .AsHCLBlock ())
113
138
if ok {
114
- tokens = append (tokens , d .tokensForBody (block .Body , depSchema , []lang.SemanticTokenModifier {})... )
139
+ tokens = append (tokens , d .tokensForBody (ctx , block .Body , depSchema , []lang.SemanticTokenModifier {})... )
115
140
}
116
141
}
117
142
118
143
return tokens
119
144
}
120
145
121
- func (d * PathDecoder ) tokensForExpression (expr hclsyntax.Expression , constraints ExprConstraints ) []lang.SemanticToken {
146
+ func (d * PathDecoder ) tokensForExpression (ctx context. Context , expr hclsyntax.Expression , constraints ExprConstraints ) []lang.SemanticToken {
122
147
tokens := make ([]lang.SemanticToken , 0 )
123
148
124
149
switch eType := expr .(type ) {
@@ -135,6 +160,31 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
135
160
}
136
161
}
137
162
163
+ address , _ := lang .TraversalToAddress (eType .AsTraversal ())
164
+ countIndexAttr := lang.Address {
165
+ lang.RootStep {
166
+ Name : "count" ,
167
+ },
168
+ lang.AttrStep {
169
+ Name : "index" ,
170
+ },
171
+ }
172
+ countAvailable := icontext .ActiveCountFromContext (ctx )
173
+ if address .Equals (countIndexAttr ) && countAvailable {
174
+ traversal := eType .AsTraversal ()
175
+ tokens = append (tokens , lang.SemanticToken {
176
+ Type : lang .TokenTraversalStep ,
177
+ Modifiers : []lang.SemanticTokenModifier {},
178
+ Range : traversal [0 ].SourceRange (),
179
+ })
180
+ tokens = append (tokens , lang.SemanticToken {
181
+ Type : lang .TokenTraversalStep ,
182
+ Modifiers : []lang.SemanticTokenModifier {},
183
+ Range : traversal [1 ].SourceRange (),
184
+ })
185
+ return tokens
186
+ }
187
+
138
188
tes , ok := constraints .TraversalExprs ()
139
189
if ok && d .pathCtx .ReferenceTargets != nil {
140
190
traversal := eType .AsTraversal ()
@@ -231,7 +281,7 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
231
281
Range : eType .NameRange ,
232
282
})
233
283
for _ , arg := range eType .Args {
234
- tokens = append (tokens , d .tokensForExpression (arg , constraints )... )
284
+ tokens = append (tokens , d .tokensForExpression (ctx , arg , constraints )... )
235
285
}
236
286
return tokens
237
287
}
@@ -249,29 +299,29 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
249
299
return tokenForTypedExpression (eType , cty .String )
250
300
}
251
301
case * hclsyntax.TemplateWrapExpr :
252
- return d .tokensForExpression (eType .Wrapped , constraints )
302
+ return d .tokensForExpression (ctx , eType .Wrapped , constraints )
253
303
case * hclsyntax.TupleConsExpr :
254
304
tc , ok := constraints .TupleConsExpr ()
255
305
if ok {
256
306
ec := ExprConstraints (tc .AnyElem )
257
307
for _ , expr := range eType .Exprs {
258
- tokens = append (tokens , d .tokensForExpression (expr , ec )... )
308
+ tokens = append (tokens , d .tokensForExpression (ctx , expr , ec )... )
259
309
}
260
310
return tokens
261
311
}
262
312
se , ok := constraints .SetExpr ()
263
313
if ok {
264
314
ec := ExprConstraints (se .Elem )
265
315
for _ , expr := range eType .Exprs {
266
- tokens = append (tokens , d .tokensForExpression (expr , ec )... )
316
+ tokens = append (tokens , d .tokensForExpression (ctx , expr , ec )... )
267
317
}
268
318
return tokens
269
319
}
270
320
le , ok := constraints .ListExpr ()
271
321
if ok {
272
322
ec := ExprConstraints (le .Elem )
273
323
for _ , expr := range eType .Exprs {
274
- tokens = append (tokens , d .tokensForExpression (expr , ec )... )
324
+ tokens = append (tokens , d .tokensForExpression (ctx , expr , ec )... )
275
325
}
276
326
return tokens
277
327
}
@@ -282,7 +332,7 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
282
332
break
283
333
}
284
334
ec := ExprConstraints (te .Elems [i ])
285
- tokens = append (tokens , d .tokensForExpression (expr , ec )... )
335
+ tokens = append (tokens , d .tokensForExpression (ctx , expr , ec )... )
286
336
}
287
337
return tokens
288
338
}
@@ -316,7 +366,7 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
316
366
})
317
367
318
368
ec := ExprConstraints (attr .Expr )
319
- tokens = append (tokens , d .tokensForExpression (item .ValueExpr , ec )... )
369
+ tokens = append (tokens , d .tokensForExpression (ctx , item .ValueExpr , ec )... )
320
370
}
321
371
return tokens
322
372
}
@@ -329,7 +379,7 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
329
379
Range : item .KeyExpr .Range (),
330
380
})
331
381
ec := ExprConstraints (me .Elem )
332
- tokens = append (tokens , d .tokensForExpression (item .ValueExpr , ec )... )
382
+ tokens = append (tokens , d .tokensForExpression (ctx , item .ValueExpr , ec )... )
333
383
}
334
384
return tokens
335
385
}
@@ -343,7 +393,7 @@ func (d *PathDecoder) tokensForExpression(expr hclsyntax.Expression, constraints
343
393
}
344
394
_ , ok = constraints .TypeDeclarationExpr ()
345
395
if ok {
346
- return d .tokensForObjectConsTypeDeclarationExpr (eType , constraints )
396
+ return d .tokensForObjectConsTypeDeclarationExpr (ctx , eType , constraints )
347
397
}
348
398
case * hclsyntax.LiteralValueExpr :
349
399
valType := eType .Val .Type ()
@@ -389,7 +439,7 @@ func isComplexTypeDeclaration(funcName string) bool {
389
439
return false
390
440
}
391
441
392
- func (d * PathDecoder ) tokensForObjectConsTypeDeclarationExpr (expr * hclsyntax.ObjectConsExpr , constraints ExprConstraints ) []lang.SemanticToken {
442
+ func (d * PathDecoder ) tokensForObjectConsTypeDeclarationExpr (ctx context. Context , expr * hclsyntax.ObjectConsExpr , constraints ExprConstraints ) []lang.SemanticToken {
393
443
tokens := make ([]lang.SemanticToken , 0 )
394
444
for _ , item := range expr .Items {
395
445
key , _ := item .KeyExpr .Value (nil )
@@ -405,7 +455,7 @@ func (d *PathDecoder) tokensForObjectConsTypeDeclarationExpr(expr *hclsyntax.Obj
405
455
Range : item .KeyExpr .Range (),
406
456
})
407
457
408
- tokens = append (tokens , d .tokensForExpression (item .ValueExpr , constraints )... )
458
+ tokens = append (tokens , d .tokensForExpression (ctx , item .ValueExpr , constraints )... )
409
459
}
410
460
return tokens
411
461
}
0 commit comments