eval: Fix lint errors.

This commit is contained in:
Qi Xiao 2019-04-18 22:15:34 +01:00
parent a8a6c71fbd
commit c8e767b2fd
21 changed files with 94 additions and 51 deletions

View File

@ -11,7 +11,13 @@ import (
)
var (
ErrArgs = errors.New("args error")
// ErrArgs is thrown when a builtin function gets erroneous arguments.
//
// TODO(xiaq): Replace this single error type with multiple types that carry
// richer error information.
ErrArgs = errors.New("args error")
// ErrNoOptAccepted is thrown when a builtin function that does not accept
// any options gets passed options.
ErrNoOptAccepted = errors.New("function does not accept any options")
)
@ -73,6 +79,9 @@ type optionsPtr interface {
SetDefaultOptions()
}
// Inputs is the type that the last parameter of a builtin function can take.
// When that is the case, it is a callback to get inputs. See the doc of
// BuiltinFn for details.
type Inputs func(func(interface{}))
var (

View File

@ -9,8 +9,6 @@ import (
// Command and process control.
var ErrNotInSameGroup = errors.New("not in the same process group")
func init() {
addBuiltinFns(map[string]interface{}{
// Command resolution

View File

@ -3,6 +3,7 @@
package eval
import (
"errors"
"os"
"os/exec"
"strconv"
@ -12,6 +13,10 @@ import (
"github.com/elves/elvish/sys"
)
// ErrNotInSameProcessGroup is thrown when the process IDs passed to fg are not
// in the same process group.
var ErrNotInSameProcessGroup = errors.New("not in the same process group")
func execFn(fm *Frame, args ...interface{}) error {
var argstrings []string
if len(args) == 0 {
@ -47,7 +52,7 @@ func fg(pids ...int) error {
if i == 0 {
thepgid = pgid
} else if pgid != thepgid {
return ErrNotInSameGroup
return ErrNotInSameProcessGroup
}
}

View File

@ -177,17 +177,16 @@ func hasKey(container, key interface{}) (bool, error) {
// XXX(xiaq): Not all types that implement Lener have numerical indices
_, err := vals.ConvertListIndex(key, len)
return err == nil, nil
} else {
var found bool
err := vals.IterateKeys(container, func(k interface{}) bool {
if key == k {
found = true
}
return !found
})
if err == nil {
return found, nil
}
var found bool
err := vals.IterateKeys(container, func(k interface{}) bool {
if key == k {
found = true
}
return !found
})
if err == nil {
return found, nil
}
return false, fmt.Errorf("couldn't get key or index of type '%s'", vals.Kind(container))
}

View File

@ -12,6 +12,7 @@ import (
// Filesystem.
// ErrStoreNotConnected is thrown by dir-history when the store is not connected.
var ErrStoreNotConnected = errors.New("store not connected")
func init() {

View File

@ -208,7 +208,7 @@ func toJSON(fm *Frame, inputs Inputs) error {
func fopen(fm *Frame, name string) (vals.File, error) {
// TODO support opening files for writing etc as well.
f, err := os.Open(name)
return vals.File{f}, err
return vals.NewFile(f), err
}
func fclose(f vals.File) error {
@ -217,7 +217,7 @@ func fclose(f vals.File) error {
func pipe() (vals.Pipe, error) {
r, w, err := os.Pipe()
return vals.Pipe{r, w}, err
return vals.NewPipe(r, w), err
}
func prclose(p vals.Pipe) error {

View File

@ -69,14 +69,12 @@ func resolve(fm *Frame, head string) string {
_, special := builtinSpecials[head]
if special {
return "special"
} else {
explode, ns, name := ParseVariableRef(head)
if !explode && fm.ResolveVar(ns, name+FnSuffix) != nil {
return "$" + head + FnSuffix
} else {
return "(external " + parse.Quote(head) + ")"
}
}
explode, ns, name := ParseVariableRef(head)
if !explode && fm.ResolveVar(ns, name+FnSuffix) != nil {
return "$" + head + FnSuffix
}
return "(external " + parse.Quote(head) + ")"
}
func source(fm *Frame, fname string) error {

View File

@ -15,7 +15,8 @@ import (
// String operations.
var ErrInput = errors.New("input error")
// ErrInputOfEawkMustBeString is thrown when eawk gets a non-string input.
var ErrInputOfEawkMustBeString = errors.New("input of eawk must be string")
func init() {
addBuiltinFns(map[string]interface{}{
@ -145,7 +146,7 @@ func eawk(fm *Frame, f Callable, inputs Inputs) error {
line, ok := v.(string)
if !ok {
broken = true
err = ErrInput
err = ErrInputOfEawkMustBeString
return
}
args := []interface{}{line}

View File

@ -427,7 +427,7 @@ func (op *ifOp) invoke(fm *Frame) error {
for i, bodyOp := range op.bodyOps {
bodies[i] = bodyOp.execlambdaOp(fm)
}
else_ := op.elseOp.execlambdaOp(fm)
elseFn := op.elseOp.execlambdaOp(fm)
for i, condOp := range op.condOps {
condValues, err := condOp.exec(fm.fork("if cond"))
if err != nil {
@ -438,7 +438,7 @@ func (op *ifOp) invoke(fm *Frame) error {
}
}
if op.elseOp.body != nil {
return else_.Call(fm.fork("if else"), NoArgs, NoOpts)
return elseFn.Call(fm.fork("if else"), NoArgs, NoOpts)
}
return nil
}
@ -624,7 +624,7 @@ func (op *tryOp) invoke(fm *Frame) error {
return err
}
except := op.exceptOp.execlambdaOp(fm)
else_ := op.elseOp.execlambdaOp(fm)
elseFn := op.elseOp.execlambdaOp(fm)
finally := op.finallyOp.execlambdaOp(fm)
err = fm.fork("try body").Call(body, NoArgs, NoOpts)
@ -639,8 +639,8 @@ func (op *tryOp) invoke(fm *Frame) error {
err = fm.fork("try except").Call(except, NoArgs, NoOpts)
}
} else {
if else_ != nil {
err = fm.fork("try else").Call(else_, NoArgs, NoOpts)
if elseFn != nil {
err = fm.fork("try else").Call(elseFn, NoArgs, NoOpts)
}
}
if finally != nil {

View File

@ -16,7 +16,8 @@ import (
// supplies does not match with what is required.
var ErrArityMismatch = errors.New("arity mismatch")
// Closure is a closure defined in elvish script.
// Closure is a closure defined in Elvish script. Each closure has its unique
// identity.
type Closure struct {
ArgNames []string
// The name for the rest argument. If empty, the function has fixed arity.
@ -37,11 +38,12 @@ func (*Closure) Kind() string {
return "fn"
}
// Equal compares by identity.
// Equal compares by address.
func (c *Closure) Equal(rhs interface{}) bool {
return c == rhs
}
// Hash returns the hash of the address of the closure.
func (c *Closure) Hash() uint32 {
return hash.Pointer(unsafe.Pointer(c))
}
@ -51,6 +53,9 @@ func (c *Closure) Repr(int) string {
return fmt.Sprintf("<closure %p>", c)
}
// Index supports the introspection of the closure. Supported keys are
// "arg-names", "rest-arg", "opt-names", "opt-defaults", "body", "def" and
// "src".
func (c *Closure) Index(k interface{}) (interface{}, bool) {
switch k {
case "arg-names":
@ -71,6 +76,7 @@ func (c *Closure) Index(k interface{}) (interface{}, bool) {
return nil, false
}
// IterateKeys calls f with all the valid keys that can be used for Index.
func (c *Closure) IterateKeys(f func(interface{}) bool) {
util.Feed(f, "arg-names", "rest-arg",
"opt-names", "opt-defaults", "body", "def", "src")

View File

@ -7,12 +7,13 @@ import (
"github.com/elves/elvish/diag"
)
// CompilationError represents a compilation error and can pretty print it.
// CompilationError represents a compilation error. It can be pretty-printed.
type CompilationError struct {
Message string
Context diag.SourceRange
}
// Error returns a plain text representation of the compilation error.
func (ce *CompilationError) Error() string {
return fmt.Sprintf("compilation error: %d-%d in %s: %s",
ce.Context.Begin, ce.Context.End, ce.Context.Name, ce.Message)
@ -23,7 +24,7 @@ func (ce *CompilationError) Range() diag.Ranging {
return ce.Context.Range()
}
// PPrint pretty-prints a compilation error.
// PPrint pretty-prints the compilation error.
func (ce *CompilationError) PPrint(indent string) string {
var buf bytes.Buffer

View File

@ -134,10 +134,9 @@ func (op *pipelineOp) invoke(fm *Frame) error {
}
}()
return nil
} else {
wg.Wait()
return ComposeExceptionsFromPipeline(errors)
}
wg.Wait()
return ComposeExceptionsFromPipeline(errors)
}
func (cp *compiler) form(n *parse.Form) effectOpBody {
@ -344,9 +343,8 @@ func (op *formOp) invoke(fm *Frame) (errRet error) {
if headFn != nil {
return headFn.Call(fm, args, convertedOpts)
} else {
return op.spaceyAssignOp.exec(fm)
}
return op.spaceyAssignOp.exec(fm)
}
func allTrue(vs []interface{}) bool {

View File

@ -175,9 +175,8 @@ func (op *elemOp) invoke(fm *Frame) ([]vars.Var, error) {
level := vars.ElementErrorLevel(err)
if level < 0 {
return nil, fm.errorpf(op.begin, op.end, "%s", err)
} else {
return nil, fm.errorpf(op.begin, op.ends[level], "%s", err)
}
return nil, fm.errorpf(op.begin, op.ends[level], "%s", err)
}
return []vars.Var{elemVar}, nil
}

View File

@ -35,10 +35,12 @@ func Cause(err error) error {
// exception.
var OK = &Exception{}
// Error returns the message of the cause of the exception.
func (exc *Exception) Error() string {
return exc.Cause.Error()
}
// PPrint pretty-prints the exception.
func (exc *Exception) PPrint(indent string) string {
buf := new(bytes.Buffer)
@ -73,10 +75,13 @@ func (exc *Exception) PPrint(indent string) string {
return buf.String()
}
// Kind returns "exception".
func (exc *Exception) Kind() string {
return "exception"
}
// Repr returns a representation of the exception. It is lossy in that it does
// not preserve the stacktrace.
func (exc *Exception) Repr(indent int) string {
if exc.Cause == nil {
return "$ok"
@ -87,19 +92,23 @@ func (exc *Exception) Repr(indent int) string {
return "?(fail " + parse.Quote(exc.Cause.Error()) + ")"
}
// Equal compares by identity.
// Equal compares by address.
func (exc *Exception) Equal(rhs interface{}) bool {
return exc == rhs
}
// Hash returns the hash of the address.
func (exc *Exception) Hash() uint32 {
return hash.Pointer(unsafe.Pointer(exc))
}
// Bool returns whether this exception has a nil cause; that is, it is $ok.
func (exc *Exception) Bool() bool {
return exc.Cause == nil
}
// Index supports introspection of the exception. Currently the only supported
// key is "cause".
func (exc *Exception) Index(k interface{}) (interface{}, bool) {
// TODO: Access to Traceback
switch k {
@ -110,6 +119,7 @@ func (exc *Exception) Index(k interface{}) (interface{}, bool) {
}
}
// IterateKeys calls f with all the valid keys that can be used in Index.
func (exc *Exception) IterateKeys(f func(interface{}) bool) {
util.Feed(f, "cause")
}
@ -120,6 +130,7 @@ type PipelineError struct {
Errors []*Exception
}
// Repr returns a representation of the pipeline error, using the multi-error builtin.
func (pe PipelineError) Repr(indent int) string {
// TODO Make a more generalized ListReprBuilder and use it here.
b := new(bytes.Buffer)
@ -137,6 +148,7 @@ func (pe PipelineError) Repr(indent int) string {
return b.String()
}
// Error returns a plain text representation of the pipeline error.
func (pe PipelineError) Error() string {
b := new(bytes.Buffer)
b.WriteString("(")
@ -197,6 +209,7 @@ var flowNames = [...]string{
"return", "break", "continue",
}
// Repr returns a representation of the flow "error".
func (f Flow) Repr(int) string {
return "?(" + f.Error() + ")"
}
@ -208,6 +221,7 @@ func (f Flow) Error() string {
return flowNames[f]
}
// PPrint pretty-prints the flow "error".
func (f Flow) PPrint(string) string {
return "\033[33;1m" + f.Error() + "\033[m"
}
@ -221,6 +235,8 @@ type ExternalCmdExit struct {
Pid int
}
// NewExternalCmdExit constructs an error for representing a non-zero exit from
// an external command.
func NewExternalCmdExit(name string, ws syscall.WaitStatus, pid int) error {
if ws.Exited() && ws.ExitStatus() == 0 {
return nil

View File

@ -14,8 +14,13 @@ import (
)
var (
// ErrExternalCmdOpts is thrown when an external command is passed Elvish
// options.
//
// TODO: Catch this kind of errors at compilation time.
ErrExternalCmdOpts = errors.New("external commands don't accept elvish options")
ErrCdNoArg = errors.New("implicit cd accepts no arguments")
// ErrImplicitCdNoArg is thrown when an implicit cd form is passed arguments.
ErrImplicitCdNoArg = errors.New("implicit cd accepts no arguments")
)
// ExternalCmd is an external command.
@ -49,7 +54,7 @@ func (e ExternalCmd) Call(fm *Frame, argVals []interface{}, opts map[string]inte
if err == nil && stat.IsDir() {
// implicit cd
if len(argVals) > 0 {
return ErrCdNoArg
return ErrImplicitCdNoArg
}
return fm.Chdir(e.Name)
}

View File

@ -12,6 +12,7 @@ func (fm *Frame) Interrupts() <-chan struct{} {
return fm.intCh
}
// ErrInterrupted is thrown when the execution is interrupted by a signal.
var ErrInterrupted = errors.New("interrupted")
// IsInterrupted reports whether there has been an interrupt.

View File

@ -9,6 +9,8 @@ import (
"github.com/elves/elvish/util"
)
// RawOptions is the type of an argument a builtin function can take to declare
// that it wants to parse options itself. See the doc of BuiltinFn for details.
type RawOptions map[string]interface{}
// Takes a raw option map and a pointer to a struct, and populate the struct

View File

@ -38,7 +38,7 @@ var (
BlackholeChan = make(chan interface{})
// DevNull is /dev/null.
DevNull *os.File
// DevNullClosedInput is a port made up from DevNull and ClosedChan,
// DevNullClosedChan is a port made up from DevNull and ClosedChan,
// suitable as placeholder input port.
DevNullClosedChan *Port
)

View File

@ -5,12 +5,13 @@ import "syscall"
// Nop on Windows.
func putSelfInFg() error { return nil }
const DETACHED_PROCESS = 0x00000008
// The bitmask for CreationFlags in SysProcAttr to start a process in background.
const detachedProcess = 0x00000008
func makeSysProcAttr(bg bool) *syscall.SysProcAttr {
flags := uint32(0)
if bg {
flags |= DETACHED_PROCESS
flags |= detachedProcess
}
return &syscall.SysProcAttr{CreationFlags: flags}
}

View File

@ -14,6 +14,8 @@ type PwdVariable struct {
var _ vars.Var = PwdVariable{}
// Get returns the current working directory. It returns /unknown/pwd when it
// cannot be determined.
func (PwdVariable) Get() interface{} {
pwd, err := os.Getwd()
// TODO: Deprecate the $pwd variable.
@ -23,6 +25,7 @@ func (PwdVariable) Get() interface{} {
return pwd
}
// Set changes the current working directory.
func (pwd PwdVariable) Set(v interface{}) error {
path, ok := v.(string)
if !ok {

View File

@ -69,8 +69,8 @@ func (t TestCase) Puts(vs ...interface{}) TestCase {
return t
}
// Puts returns an altered Test that requires the source code to produce the
// specified strings in the value channel when evaluated.
// PutsStrings returns an altered Test that requires the source code to produce
// the specified strings in the value channel when evaluated.
func (t TestCase) PutsStrings(ss []string) TestCase {
t.want.out = make([]interface{}, len(ss))
for i, s := range ss {
@ -105,8 +105,8 @@ func Test(t *testing.T, tests ...TestCase) {
TestWithSetup(t, func(*Evaler) {}, tests...)
}
// Test runs test cases. For each test case, a new Evaler is created with
// NewEvaler and passed to the setup function.
// TestWithSetup runs test cases. For each test case, a new Evaler is created
// with NewEvaler and passed to the setup function.
func TestWithSetup(t *testing.T, setup func(*Evaler), tests ...TestCase) {
for _, tt := range tests {
ev := NewEvaler()