mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-12 17:27:50 +08:00
87656c99fa
The `AnyError` placeholder error can cause tests to succeed for errors other than what was expected. That is, the use of `AnyError` can mask bugs in a unit test. So replace it with the specific error, or error type, the test expects to be raised. This does not remove the anyError structure because it is used in the TestCase.DoesNotCompile() method. To keep the size of this change as small as possible I want to defer updating that use to a separate change. However, remove the public AnyError var so future test writers don't attempt to use it.
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package eval
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"src.elv.sh/pkg/eval/vals"
|
|
"src.elv.sh/pkg/parse"
|
|
"src.elv.sh/pkg/strutil"
|
|
)
|
|
|
|
type BadOption struct {
|
|
OptName string
|
|
}
|
|
|
|
func (e BadOption) Error() string {
|
|
return "unknown option: " + parse.Quote(e.OptName)
|
|
}
|
|
|
|
// RawOptions is the type of an argument a Go-native function can take to
|
|
// declare that it wants to parse options itself. See the doc of NewGoFn for
|
|
// details.
|
|
type RawOptions map[string]interface{}
|
|
|
|
// Takes a raw option map and a pointer to a struct, and populate the struct
|
|
// with options. A field named FieldName corresponds to the option named
|
|
// field-name, unless the field has a explicit "name" tag. Fields typed
|
|
// ParsedOptions are ignored.
|
|
func scanOptions(rawOpts RawOptions, ptr interface{}) error {
|
|
ptrValue := reflect.ValueOf(ptr)
|
|
if ptrValue.Kind() != reflect.Ptr || ptrValue.Elem().Kind() != reflect.Struct {
|
|
return fmt.Errorf(
|
|
"internal bug: need struct ptr to scan options, got %T", ptr)
|
|
}
|
|
|
|
// fieldIdxForOpt maps option name to the index of field in `struc`.
|
|
fieldIdxForOpt := make(map[string]int)
|
|
struc := ptrValue.Elem()
|
|
for i := 0; i < struc.Type().NumField(); i++ {
|
|
if !struc.Field(i).CanSet() {
|
|
continue // ignore unexported fields
|
|
}
|
|
|
|
f := struc.Type().Field(i)
|
|
optName := f.Tag.Get("name")
|
|
if optName == "" {
|
|
optName = strutil.CamelToDashed(f.Name)
|
|
}
|
|
fieldIdxForOpt[optName] = i
|
|
}
|
|
|
|
for k, v := range rawOpts {
|
|
fieldIdx, ok := fieldIdxForOpt[k]
|
|
if !ok {
|
|
return BadOption{k}
|
|
}
|
|
err := vals.ScanToGo(v, struc.Field(fieldIdx).Addr().Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|