Skip to content

Commit 0fad89c

Browse files
jedevccrazy-max
authored andcommitted
bake: avoid nesting error diagnostics
With changes to the lazy evaluation, the evaluation order is no longer fixed - this means that we can follow long and confusing paths to get to an error. Because of the co-recursive nature of the lazy evaluation, we need to take special care that the original HCL diagnostics are not discarded and are preserved so that the original source of the error can be detected. Preserving the full trace is not necessary, and probably not useful to the user - all of the file that is not lazily loaded will be eagerly loaded after all struct blocks are loaded - so the error would be found regardless. Signed-off-by: Justin Chadwell <[email protected]> (cherry picked from commit fbb4f4d)
1 parent 661af29 commit 0fad89c

2 files changed

Lines changed: 30 additions & 80 deletions

File tree

bake/hclparser/expr.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,7 @@ func funcCalls(exp hcl.Expression) ([]string, hcl.Diagnostics) {
1414
if !ok {
1515
fns, err := jsonFuncCallsRecursive(exp)
1616
if err != nil {
17-
return nil, hcl.Diagnostics{
18-
&hcl.Diagnostic{
19-
Severity: hcl.DiagError,
20-
Summary: "Invalid expression",
21-
Detail: err.Error(),
22-
Subject: exp.Range().Ptr(),
23-
Context: exp.Range().Ptr(),
24-
},
25-
}
17+
return nil, wrapErrorDiagnostic("Invalid expression", err, exp.Range().Ptr(), exp.Range().Ptr())
2618
}
2719
return fns, nil
2820
}

bake/hclparser/hclparser.go

Lines changed: 29 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,7 @@ func (p *parser) loadDeps(exp hcl.Expression, exclude map[string]struct{}, allow
7575
if allowMissing && errors.Is(err, errUndefined) {
7676
continue
7777
}
78-
return hcl.Diagnostics{
79-
&hcl.Diagnostic{
80-
Severity: hcl.DiagError,
81-
Summary: "Invalid expression",
82-
Detail: err.Error(),
83-
Subject: exp.Range().Ptr(),
84-
Context: exp.Range().Ptr(),
85-
},
86-
}
78+
return wrapErrorDiagnostic("Invalid expression", err, exp.Range().Ptr(), exp.Range().Ptr())
8779
}
8880
}
8981

@@ -136,30 +128,14 @@ func (p *parser) loadDeps(exp hcl.Expression, exclude map[string]struct{}, allow
136128
if allowMissing && errors.Is(err, errUndefined) {
137129
continue
138130
}
139-
return hcl.Diagnostics{
140-
&hcl.Diagnostic{
141-
Severity: hcl.DiagError,
142-
Summary: "Invalid expression",
143-
Detail: err.Error(),
144-
Subject: v.SourceRange().Ptr(),
145-
Context: v.SourceRange().Ptr(),
146-
},
147-
}
131+
return wrapErrorDiagnostic("Invalid expression", err, exp.Range().Ptr(), exp.Range().Ptr())
148132
}
149133
} else {
150134
if err := p.resolveValue(v.RootName()); err != nil {
151135
if allowMissing && errors.Is(err, errUndefined) {
152136
continue
153137
}
154-
return hcl.Diagnostics{
155-
&hcl.Diagnostic{
156-
Severity: hcl.DiagError,
157-
Summary: "Invalid expression",
158-
Detail: err.Error(),
159-
Subject: v.SourceRange().Ptr(),
160-
Context: v.SourceRange().Ptr(),
161-
},
162-
}
138+
return wrapErrorDiagnostic("Invalid expression", err, exp.Range().Ptr(), exp.Range().Ptr())
163139
}
164140
}
165141
}
@@ -325,14 +301,7 @@ func (p *parser) resolveValue(name string) (err error) {
325301
func (p *parser) resolveBlock(block *hcl.Block, target *hcl.BodySchema) (err error) {
326302
name := block.Labels[0]
327303
if err := p.opt.ValidateLabel(name); err != nil {
328-
return hcl.Diagnostics{
329-
&hcl.Diagnostic{
330-
Severity: hcl.DiagError,
331-
Summary: "Invalid name",
332-
Detail: err.Error(),
333-
Subject: &block.LabelRanges[0],
334-
},
335-
}
304+
return wrapErrorDiagnostic("Invalid name", err, &block.LabelRanges[0], &block.LabelRanges[0])
336305
}
337306

338307
if _, ok := p.doneB[block]; !ok {
@@ -584,15 +553,7 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
584553
return diags
585554
}
586555
r := p.vars[k].Body.MissingItemRange()
587-
return hcl.Diagnostics{
588-
&hcl.Diagnostic{
589-
Severity: hcl.DiagError,
590-
Summary: "Invalid value",
591-
Detail: err.Error(),
592-
Subject: &r,
593-
Context: &r,
594-
},
595-
}
556+
return wrapErrorDiagnostic("Invalid value", err, &r, &r)
596557
}
597558
}
598559

@@ -615,15 +576,7 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
615576
}
616577
}
617578
}
618-
return hcl.Diagnostics{
619-
&hcl.Diagnostic{
620-
Severity: hcl.DiagError,
621-
Summary: "Invalid function",
622-
Detail: err.Error(),
623-
Subject: subject,
624-
Context: context,
625-
},
626-
}
579+
return wrapErrorDiagnostic("Invalid function", err, subject, context)
627580
}
628581
}
629582

@@ -684,15 +637,7 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
684637
continue
685638
}
686639
} else {
687-
return hcl.Diagnostics{
688-
&hcl.Diagnostic{
689-
Severity: hcl.DiagError,
690-
Summary: "Invalid attribute",
691-
Detail: err.Error(),
692-
Subject: &b.LabelRanges[0],
693-
Context: &b.DefRange,
694-
},
695-
}
640+
return wrapErrorDiagnostic("Invalid block", err, &b.LabelRanges[0], &b.DefRange)
696641
}
697642
}
698643

@@ -737,21 +682,34 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
737682
if diags, ok := err.(hcl.Diagnostics); ok {
738683
return diags
739684
}
740-
return hcl.Diagnostics{
741-
&hcl.Diagnostic{
742-
Severity: hcl.DiagError,
743-
Summary: "Invalid attribute",
744-
Detail: err.Error(),
745-
Subject: &p.attrs[k].Range,
746-
Context: &p.attrs[k].Range,
747-
},
748-
}
685+
return wrapErrorDiagnostic("Invalid attribute", err, &p.attrs[k].Range, &p.attrs[k].Range)
749686
}
750687
}
751688

752689
return nil
753690
}
754691

692+
// wrapErrorDiagnostic wraps an error into a hcl.Diagnostics object.
693+
// If the error is already an hcl.Diagnostics object, it is returned as is.
694+
func wrapErrorDiagnostic(message string, err error, subject *hcl.Range, context *hcl.Range) hcl.Diagnostics {
695+
switch err := err.(type) {
696+
case *hcl.Diagnostic:
697+
return hcl.Diagnostics{err}
698+
case hcl.Diagnostics:
699+
return err
700+
default:
701+
return hcl.Diagnostics{
702+
&hcl.Diagnostic{
703+
Severity: hcl.DiagError,
704+
Summary: message,
705+
Detail: err.Error(),
706+
Subject: subject,
707+
Context: context,
708+
},
709+
}
710+
}
711+
}
712+
755713
func setLabel(v reflect.Value, lbl string) int {
756714
// cache field index?
757715
numFields := v.Elem().Type().NumField()

0 commit comments

Comments
 (0)