-
Notifications
You must be signed in to change notification settings - Fork 9.6k
/
hcl.go
141 lines (127 loc) · 3.35 KB
/
hcl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package tfdiags
import (
"fmt"
"github.com/hashicorp/hcl/v2"
)
// hclDiagnostic is a Diagnostic implementation that wraps a HCL Diagnostic
type hclDiagnostic struct {
diag *hcl.Diagnostic
}
var _ Diagnostic = hclDiagnostic{}
func (d hclDiagnostic) Severity() Severity {
switch d.diag.Severity {
case hcl.DiagWarning:
return Warning
default:
return Error
}
}
func (d hclDiagnostic) Description() Description {
return Description{
Summary: d.diag.Summary,
Detail: d.diag.Detail,
}
}
func (d hclDiagnostic) Source() Source {
var ret Source
if d.diag.Subject != nil {
rng := SourceRangeFromHCL(*d.diag.Subject)
ret.Subject = &rng
}
if d.diag.Context != nil {
rng := SourceRangeFromHCL(*d.diag.Context)
ret.Context = &rng
}
return ret
}
func (d hclDiagnostic) FromExpr() *FromExpr {
if d.diag.Expression == nil || d.diag.EvalContext == nil {
return nil
}
return &FromExpr{
Expression: d.diag.Expression,
EvalContext: d.diag.EvalContext,
}
}
// SourceRangeFromHCL constructs a SourceRange from the corresponding range
// type within the HCL package.
func SourceRangeFromHCL(hclRange hcl.Range) SourceRange {
return SourceRange{
Filename: hclRange.Filename,
Start: SourcePos{
Line: hclRange.Start.Line,
Column: hclRange.Start.Column,
Byte: hclRange.Start.Byte,
},
End: SourcePos{
Line: hclRange.End.Line,
Column: hclRange.End.Column,
Byte: hclRange.End.Byte,
},
}
}
// ToHCL constructs a HCL Range from the receiving SourceRange. This is the
// opposite of SourceRangeFromHCL.
func (r SourceRange) ToHCL() hcl.Range {
return hcl.Range{
Filename: r.Filename,
Start: hcl.Pos{
Line: r.Start.Line,
Column: r.Start.Column,
Byte: r.Start.Byte,
},
End: hcl.Pos{
Line: r.End.Line,
Column: r.End.Column,
Byte: r.End.Byte,
},
}
}
// ToHCL constructs a hcl.Diagnostics containing the same diagnostic messages
// as the receiving tfdiags.Diagnostics.
//
// This conversion preserves the data that HCL diagnostics are able to
// preserve but would be lossy in a round trip from tfdiags to HCL and then
// back to tfdiags, because it will lose the specific type information of
// the source diagnostics. In most cases this will not be a significant
// problem, but could produce an awkward result in some special cases such
// as converting the result of ConsolidateWarnings, which will force the
// resulting warning groups to be flattened early.
func (d Diagnostics) ToHCL() hcl.Diagnostics {
if len(d) == 0 {
return nil
}
ret := make(hcl.Diagnostics, len(d))
for i, diag := range d {
severity := diag.Severity()
desc := diag.Description()
source := diag.Source()
fromExpr := diag.FromExpr()
hclDiag := &hcl.Diagnostic{
Summary: desc.Summary,
Detail: desc.Detail,
}
switch severity {
case Warning:
hclDiag.Severity = hcl.DiagWarning
case Error:
hclDiag.Severity = hcl.DiagError
default:
// The above should always be exhaustive for all of the valid
// Severity values in this package.
panic(fmt.Sprintf("unknown diagnostic severity %s", severity))
}
if source.Subject != nil {
hclDiag.Subject = source.Subject.ToHCL().Ptr()
}
if source.Context != nil {
hclDiag.Context = source.Context.ToHCL().Ptr()
}
if fromExpr != nil {
hclDiag.Expression = fromExpr.Expression
hclDiag.EvalContext = fromExpr.EvalContext
}
ret[i] = hclDiag
}
return ret
}