terraform/internal/tfdiags/source_range.go

36 lines
763 B
Go
Raw Normal View History

tfdiags: new package for normalizing error and warning messages Currently we lean heavily on the Go error type as our primary means of describing errors, and along with that use several more specialized implementations of it in different spots for additional capabilities such as multiple errors in one object, source code range references, etc. We also have a rather ad-hoc approach of returning an array of warnings from certain functions along with one or multiple errors. This rather-disorganized approach makes it hard for us to present user-facing error messages consistently. As a step towards mitigating this, package tfdiags provides a model for user-facing error and warning messages and helper functions for creating them from various other error and warning types used elsewhere in Terraform. This mechanism is intended to be used to report errors and warnings where the audience is the Terraform user, and so it may go a few layers deep down the call stack into codepaths like config parsing, interpolation, etc but is primarily a UX concern. The deepest reaches of Terraform core will continue using "error" as normal, with higher layers preparing error messages for presentation to the user. To avoid needing to change the interface of every function that might generate error diagnostics, the Diagnostics type can be "smuggled" via an error value through other APIs and then unwrapped at the other end, though it will lose any naked warnings (without at least one error) along the way, and so codepaths that are expected to generate warnings (validation, primarily) should use the concrete Diagnostics type throughout the call chain.
2017-10-05 02:13:29 +02:00
package tfdiags
import (
"fmt"
"os"
"path/filepath"
)
tfdiags: new package for normalizing error and warning messages Currently we lean heavily on the Go error type as our primary means of describing errors, and along with that use several more specialized implementations of it in different spots for additional capabilities such as multiple errors in one object, source code range references, etc. We also have a rather ad-hoc approach of returning an array of warnings from certain functions along with one or multiple errors. This rather-disorganized approach makes it hard for us to present user-facing error messages consistently. As a step towards mitigating this, package tfdiags provides a model for user-facing error and warning messages and helper functions for creating them from various other error and warning types used elsewhere in Terraform. This mechanism is intended to be used to report errors and warnings where the audience is the Terraform user, and so it may go a few layers deep down the call stack into codepaths like config parsing, interpolation, etc but is primarily a UX concern. The deepest reaches of Terraform core will continue using "error" as normal, with higher layers preparing error messages for presentation to the user. To avoid needing to change the interface of every function that might generate error diagnostics, the Diagnostics type can be "smuggled" via an error value through other APIs and then unwrapped at the other end, though it will lose any naked warnings (without at least one error) along the way, and so codepaths that are expected to generate warnings (validation, primarily) should use the concrete Diagnostics type throughout the call chain.
2017-10-05 02:13:29 +02:00
type SourceRange struct {
Filename string
Start, End SourcePos
}
type SourcePos struct {
Line, Column, Byte int
}
// StartString returns a string representation of the start of the range,
// including the filename and the line and column numbers.
func (r SourceRange) StartString() string {
filename := r.Filename
// We'll try to relative-ize our filename here so it's less verbose
// in the common case of being in the current working directory. If not,
// we'll just show the full path.
wd, err := os.Getwd()
if err == nil {
relFn, err := filepath.Rel(wd, filename)
if err == nil {
filename = relFn
}
}
return fmt.Sprintf("%s:%d,%d", filename, r.Start.Line, r.Start.Column)
}