Skip to content

Commit ae53b93

Browse files
authored
Merge pull request #692 from hashicorp/support-incomplete-references-in-object-items
feat: return an `ExprSyntaxError` for invalid references that end in a dot
2 parents 360ae57 + 117baa8 commit ae53b93

File tree

2 files changed

+101
-3
lines changed

2 files changed

+101
-3
lines changed

hclsyntax/parser.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,9 +811,16 @@ Traversal:
811811
// will probably be misparsed until we hit something that
812812
// allows us to re-sync.
813813
//
814-
// We will probably need to do something better here eventually
815-
// in order to support autocomplete triggered by typing a
816-
// period.
814+
// Returning an ExprSyntaxError allows us to pass more information
815+
// about the invalid expression to the caller, which can then
816+
// use this for example for completions that happen after typing
817+
// a dot in an editor.
818+
ret = &ExprSyntaxError{
819+
Placeholder: cty.DynamicVal,
820+
ParseDiags: diags,
821+
SrcRange: hcl.RangeBetween(from.Range(), dot.Range),
822+
}
823+
817824
p.setRecovery()
818825
}
819826

@@ -1516,6 +1523,16 @@ func (p *parser) parseObjectCons() (Expression, hcl.Diagnostics) {
15161523
diags = append(diags, valueDiags...)
15171524

15181525
if p.recovery && valueDiags.HasErrors() {
1526+
// If the value is an ExprSyntaxError, we can add an item with it, even though we will recover afterwards
1527+
// This allows downstream consumers to still retrieve this first invalid item, even though following items
1528+
// won't be parsed. This is useful for supplying completions.
1529+
if exprSyntaxError, ok := value.(*ExprSyntaxError); ok {
1530+
items = append(items, ObjectConsItem{
1531+
KeyExpr: key,
1532+
ValueExpr: exprSyntaxError,
1533+
})
1534+
}
1535+
15191536
// If expression parsing failed then we are probably in a strange
15201537
// place in the token stream, so we'll bail out and try to reset
15211538
// to after our closing brace to allow parsing to continue.

hclsyntax/parser_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,6 +2672,87 @@ block "valid" {}
26722672
},
26732673
},
26742674
},
2675+
{
2676+
"a = { b = c. }",
2677+
1,
2678+
&Body{
2679+
Attributes: Attributes{
2680+
"a": {
2681+
Name: "a",
2682+
Expr: &ObjectConsExpr{
2683+
Items: []ObjectConsItem{
2684+
{
2685+
KeyExpr: &ObjectConsKeyExpr{
2686+
Wrapped: &ScopeTraversalExpr{
2687+
Traversal: hcl.Traversal{
2688+
hcl.TraverseRoot{
2689+
Name: "b",
2690+
SrcRange: hcl.Range{
2691+
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
2692+
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
2693+
},
2694+
},
2695+
},
2696+
SrcRange: hcl.Range{
2697+
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
2698+
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
2699+
},
2700+
},
2701+
},
2702+
ValueExpr: &ExprSyntaxError{
2703+
Placeholder: cty.DynamicVal,
2704+
SrcRange: hcl.Range{
2705+
Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},
2706+
End: hcl.Pos{Line: 1, Column: 13, Byte: 12},
2707+
},
2708+
ParseDiags: hcl.Diagnostics{
2709+
{
2710+
Severity: hcl.DiagError,
2711+
Summary: "Invalid attribute name",
2712+
Detail: "An attribute name is required after a dot.",
2713+
Subject: &hcl.Range{
2714+
Start: hcl.Pos{Line: 1, Column: 14, Byte: 13},
2715+
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
2716+
},
2717+
},
2718+
},
2719+
},
2720+
},
2721+
},
2722+
SrcRange: hcl.Range{
2723+
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
2724+
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
2725+
},
2726+
OpenRange: hcl.Range{
2727+
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
2728+
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
2729+
},
2730+
},
2731+
SrcRange: hcl.Range{
2732+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
2733+
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
2734+
},
2735+
NameRange: hcl.Range{
2736+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
2737+
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
2738+
},
2739+
EqualsRange: hcl.Range{
2740+
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
2741+
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
2742+
},
2743+
},
2744+
},
2745+
Blocks: Blocks{},
2746+
SrcRange: hcl.Range{
2747+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
2748+
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
2749+
},
2750+
EndRange: hcl.Range{
2751+
Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},
2752+
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
2753+
},
2754+
},
2755+
},
26752756
}
26762757

26772758
for _, test := range tests {

0 commit comments

Comments
 (0)