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