hashicorp / hashicorp/hcl

hclsyntax: Recovery of outer `ObjectConsExpr` with empty `TemplateExpr`

Open
#641 1 comment 0 reactions 0 assignees View on GitHub
enhancement
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.