hclsyntax: Recovery of outer `ObjectConsExpr` with empty `TemplateExpr`
- Dominant language
- Go
- Stars
- 5.8k
- Forks
- 657
- Avg merge
- 20h 36m
- Merged PRs (30d)
- 6
Description
During the work to support template expressions in the language server, we discovered a different recovery behavior when dealing with empty template expressions.
### "Regular" / Expected
```go
package main
import (
"log"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
func main() {
cfg := `attr = "foo-${}-bar"`
f, diags := hclsyntax.ParseConfig([]byte(cfg), "", hcl.InitialPos)
if len(diags) > 0 {
log.Printf("diagnostics: %s", diags)
}
attrs, _ := f.Body.JustAttributes()
log.Printf("expression: %#v", attrs["attr"].Expr)
}
```
In this case, we get a diagnostic for an invalid expression, as expected, but the parsed configuration still contains a `TemplateExpr` with three parts. The second `LiteralValueExpr` corresponds to the empty template expression `${}`.
```
2009/11/10 23:00:00 diagnostics: :1,15-16: Invalid expression; Expected the start of an expression, but found an invalid expression token.
2009/11/10 23:00:00 expression: &hclsyntax.TemplateExpr{Parts:[]hclsyntax.Expression{(*hclsyntax.LiteralValueExpr)(0xc000062720), (*hclsyntax.LiteralValueExpr)(0xc000062480), (*hclsyntax.LiteralValueExpr)(0xc000062780)}, SrcRange:hcl.Range{Filename:"", Start:hcl.Pos{Line:1, Column:8, Byte:7}, End:hcl.Pos{Line:1, Column:21, Byte:20}}}
```
### Inside `ObjectConsExpr`
```go
cfg := `attr = { foo = "foo-${}-bar" }`
```
If we encounter the empty template expression inside an object value, the parser stops and recovers the object without any items. All entries before the template expression are part of the result, all items after it are lost.
```
2009/11/10 23:00:00 diagnostics: :1,23-24: Invalid expression; Expected the start of an expression, but found an invalid expression token.
2009/11/10 23:00:00 expression: &hclsyntax.ObjectConsExpr{Items:[]hclsyntax.ObjectConsItem(nil), SrcRange:hcl.Range{Filename:"", Start:hcl.Pos{Line:1, Column:8, Byte:7}, End:hcl.Pos{Line:1, Column:31, Byte:30}}, OpenRange:hcl.Range{Filename:"", Start:hcl.Pos{Line:1, Column:8, Byte:7}, End:hcl.Pos{Line:1, Column:9, Byte:8}}}
```
This looks a bit similar to #597, but in this case the configuration is _nearly_ valid and works in the context of a simple attribute.
### Proposal
Explore whether it might be possible to handle the empty template expression differently than the default recovery on invalid value expression?https://github.com/hashicorp/hcl/blob/c964a71ca32006c9e7a0730b5a0e1dd60b05d308/hclsyntax/parser.go#L1496-L1505
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.