databricks-cli/libs/diag/diagnostic.go

137 lines
3.1 KiB
Go

package diag
import (
"errors"
"fmt"
"github.com/databricks/cli/libs/dyn"
)
// Convenience struct for retaining a 1:1 mapping between locations and paths.
type LocationPathPair struct {
// Locations are the source code locations associated with the diagnostic message.
L dyn.Location
// Paths are paths to the values in the configuration tree that the diagnostic is associated with.
P dyn.Path
}
type Diagnostic struct {
Severity Severity
// Summary is a short description of the diagnostic.
// This is expected to be a single line and always present.
Summary string
// Detail is a longer description of the diagnostic.
// This may be multiple lines and may be nil.
Detail string
// LocationPathPairs are the source code locations and paths associated with the diagnostic message.
// It may be empty if there are no associated locations and paths.
LocationPathPairs []LocationPathPair
// It may be empty if there are no associated locations.
Locations []dyn.Location
// It may be nil if there are no associated paths.
Paths []dyn.Path
// A diagnostic ID. Only used for select diagnostic messages.
ID ID
}
// Errorf creates a new error diagnostic.
func Errorf(format string, args ...any) Diagnostics {
return []Diagnostic{
{
Severity: Error,
Summary: fmt.Sprintf(format, args...),
},
}
}
// FromErr returns a new error diagnostic from the specified error, if any.
func FromErr(err error) Diagnostics {
if err == nil {
return nil
}
return []Diagnostic{
{
Severity: Error,
Summary: err.Error(),
},
}
}
// Warningf creates a new warning diagnostic.
func Warningf(format string, args ...any) Diagnostics {
return []Diagnostic{
{
Severity: Warning,
Summary: fmt.Sprintf(format, args...),
},
}
}
// Infof creates a new info diagnostic.
func Infof(format string, args ...any) Diagnostics {
return []Diagnostic{
{
Severity: Info,
Summary: fmt.Sprintf(format, args...),
},
}
}
// Diagnostics holds zero or more instances of [Diagnostic].
type Diagnostics []Diagnostic
// Append adds a new diagnostic to the end of the list.
func (ds Diagnostics) Append(d Diagnostic) Diagnostics {
return append(ds, d)
}
// Extend adds all diagnostics from another list to the end of the list.
func (ds Diagnostics) Extend(other Diagnostics) Diagnostics {
return append(ds, other...)
}
// HasError returns true if any of the diagnostics are errors.
func (ds Diagnostics) HasError() bool {
for _, d := range ds {
if d.Severity == Error {
return true
}
}
return false
}
// Return first error in the set of diagnostics.
func (ds Diagnostics) Error() error {
for _, d := range ds {
if d.Severity == Error {
message := d.Detail
if message == "" {
message = d.Summary
}
if d.ID != "" {
message = string(d.ID) + ": " + message
}
return errors.New(message)
}
}
return nil
}
// Filter returns a new list of diagnostics that match the specified severity.
func (ds Diagnostics) Filter(severity Severity) Diagnostics {
var out Diagnostics
for _, d := range ds {
if d.Severity == severity {
out = append(out, d)
}
}
return out
}