diff --git a/command/views/json/diagnostic.go b/command/views/json/diagnostic.go index 12a8d2730..1290e6bb5 100644 --- a/command/views/json/diagnostic.go +++ b/command/views/json/diagnostic.go @@ -133,6 +133,12 @@ func NewDiagnostic(diag tfdiags.Diagnostic, sources map[string][]byte) *Diagnost // We'll borrow HCL's range implementation here, because it has some // handy features to help us produce a nice source code snippet. highlightRange := sourceRefs.Subject.ToHCL() + + // Some diagnostic sources fail to set the end of the subject range. + if highlightRange.End == (hcl.Pos{}) { + highlightRange.End = highlightRange.Start + } + snippetRange := highlightRange if sourceRefs.Context != nil { snippetRange = sourceRefs.Context.ToHCL() diff --git a/command/views/json/diagnostic_test.go b/command/views/json/diagnostic_test.go index 8308b18a6..a11d815e2 100644 --- a/command/views/json/diagnostic_test.go +++ b/command/views/json/diagnostic_test.go @@ -246,6 +246,44 @@ func TestNewDiagnostic(t *testing.T) { }, }, }, + "error with unset highlight end position": { + &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "There is no end", + Detail: "But there is a beginning", + Subject: &hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{Line: 1, Column: 16, Byte: 15}, + End: hcl.Pos{Line: 0, Column: 0, Byte: 0}, + }, + }, + &Diagnostic{ + Severity: "error", + Summary: "There is no end", + Detail: "But there is a beginning", + Range: &DiagnosticRange{ + Filename: "test.tf", + Start: Pos{ + Line: 1, + Column: 16, + Byte: 15, + }, + End: Pos{ + Line: 1, + Column: 17, + Byte: 16, + }, + }, + Snippet: &DiagnosticSnippet{ + Context: strPtr(`resource "test_resource" "test"`), + Code: `resource "test_resource" "test" {`, + StartLine: 1, + HighlightStartOffset: 15, + HighlightEndOffset: 16, + Values: []DiagnosticExpressionValue{}, + }, + }, + }, "error with source code subject and known expression": { &hcl.Diagnostic{ Severity: hcl.DiagError, @@ -698,6 +736,11 @@ func TestNewDiagnostic(t *testing.T) { "diagnostic", fmt.Sprintf("%s.json", strings.ReplaceAll(name, " ", "-")), ) + + // Generate golden reference by uncommenting the next two lines: + // gotBytes = append(gotBytes, '\n') + // os.WriteFile(filename, gotBytes, 0644) + wantFile, err := os.Open(filename) if err != nil { t.Fatalf("failed to open golden file: %s", err) diff --git a/command/views/json/testdata/diagnostic/error-with-unset-highlight-end-position.json b/command/views/json/testdata/diagnostic/error-with-unset-highlight-end-position.json new file mode 100644 index 000000000..1f7351f09 --- /dev/null +++ b/command/views/json/testdata/diagnostic/error-with-unset-highlight-end-position.json @@ -0,0 +1,26 @@ +{ + "severity": "error", + "summary": "There is no end", + "detail": "But there is a beginning", + "range": { + "filename": "test.tf", + "start": { + "line": 1, + "column": 16, + "byte": 15 + }, + "end": { + "line": 1, + "column": 17, + "byte": 16 + } + }, + "snippet": { + "context": "resource \"test_resource\" \"test\"", + "code": "resource \"test_resource\" \"test\" {", + "start_line": 1, + "highlight_start_offset": 15, + "highlight_end_offset": 16, + "values": [] + } +}