github.com/hashicorp/hcl/v2@v2.20.0/cmd/hcldec/diags_json.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package main
     5  
     6  import (
     7  	"encoding/json"
     8  	"io"
     9  
    10  	"github.com/hashicorp/hcl/v2"
    11  )
    12  
    13  type jsonDiagWriter struct {
    14  	w     io.Writer
    15  	diags hcl.Diagnostics
    16  }
    17  
    18  var _ hcl.DiagnosticWriter = &jsonDiagWriter{}
    19  
    20  func (wr *jsonDiagWriter) WriteDiagnostic(diag *hcl.Diagnostic) error {
    21  	wr.diags = append(wr.diags, diag)
    22  	return nil
    23  }
    24  
    25  func (wr *jsonDiagWriter) WriteDiagnostics(diags hcl.Diagnostics) error {
    26  	wr.diags = append(wr.diags, diags...)
    27  	return nil
    28  }
    29  
    30  func (wr *jsonDiagWriter) Flush() error {
    31  	if len(wr.diags) == 0 {
    32  		return nil
    33  	}
    34  
    35  	type PosJSON struct {
    36  		Line   int `json:"line"`
    37  		Column int `json:"column"`
    38  		Byte   int `json:"byte"`
    39  	}
    40  	type RangeJSON struct {
    41  		Filename string  `json:"filename"`
    42  		Start    PosJSON `json:"start"`
    43  		End      PosJSON `json:"end"`
    44  	}
    45  	type DiagnosticJSON struct {
    46  		Severity string     `json:"severity"`
    47  		Summary  string     `json:"summary"`
    48  		Detail   string     `json:"detail,omitempty"`
    49  		Subject  *RangeJSON `json:"subject,omitempty"`
    50  	}
    51  	type DiagnosticsJSON struct {
    52  		Diagnostics []DiagnosticJSON `json:"diagnostics"`
    53  	}
    54  
    55  	diagsJSON := make([]DiagnosticJSON, 0, len(wr.diags))
    56  	for _, diag := range wr.diags {
    57  		var diagJSON DiagnosticJSON
    58  
    59  		switch diag.Severity {
    60  		case hcl.DiagError:
    61  			diagJSON.Severity = "error"
    62  		case hcl.DiagWarning:
    63  			diagJSON.Severity = "warning"
    64  		default:
    65  			diagJSON.Severity = "(unknown)" // should never happen
    66  		}
    67  
    68  		diagJSON.Summary = diag.Summary
    69  		diagJSON.Detail = diag.Detail
    70  		if diag.Subject != nil {
    71  			diagJSON.Subject = &RangeJSON{}
    72  			sJSON := diagJSON.Subject
    73  			rng := diag.Subject
    74  			sJSON.Filename = rng.Filename
    75  			sJSON.Start.Line = rng.Start.Line
    76  			sJSON.Start.Column = rng.Start.Column
    77  			sJSON.Start.Byte = rng.Start.Byte
    78  			sJSON.End.Line = rng.End.Line
    79  			sJSON.End.Column = rng.End.Column
    80  			sJSON.End.Byte = rng.End.Byte
    81  		}
    82  
    83  		diagsJSON = append(diagsJSON, diagJSON)
    84  	}
    85  
    86  	src, err := json.MarshalIndent(DiagnosticsJSON{diagsJSON}, "", "  ")
    87  	if err != nil {
    88  		return err
    89  	}
    90  	_, err = wr.w.Write(src)
    91  	wr.w.Write([]byte{'\n'})
    92  	return err
    93  }
    94  
    95  type flusher interface {
    96  	Flush() error
    97  }
    98  
    99  func flush(maybeFlusher interface{}) error {
   100  	if f, ok := maybeFlusher.(flusher); ok {
   101  		return f.Flush()
   102  	}
   103  	return nil
   104  }