From e93dfe8062abbfb1b6588270f404da6b2036ea11 Mon Sep 17 00:00:00 2001 From: Pawan Rawal Date: Sat, 24 Feb 2018 20:10:45 +1100 Subject: [PATCH] Better error messages (#24) * Print proper error messages while using contract subcommands and also exit with status code 1. * Make -in a flag, also remove dot from avm extension. * Work on feedback by Anthony. * Update README and VERSION --- README.md | 6 ++--- cli/.gitignore | 1 + cli/main.go | 1 + cli/smartcontract/smart_contract.go | 38 +++++++++++++++++++++-------- pkg/vm/compiler/README.md | 6 +++++ pkg/vm/compiler/compiler.go | 9 +++---- 6 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 cli/.gitignore diff --git a/README.md b/README.md index 602bdc6a2..60af7e999 100644 --- a/README.md +++ b/README.md @@ -117,20 +117,20 @@ TODO ### Compile a smart contract ``` -./bin/neo-go contract compile mycontract.go +./bin/neo-go contract compile -i mycontract.go ``` By default the filename will be the name of your .go file with the .avm extension, the file will be located in the same directory where you called the command from. If you want another location for your compiled contract: ``` -./bin/neo-go contract compile mycontract.go --out /Users/foo/bar/contract.avm +./bin/neo-go contract compile -i mycontract.go --out /Users/foo/bar/contract.avm ``` ### Debugging your smart contract You can dump the opcodes generated by the compiler with the following command: ``` -./bin/neo-go contract opdump mycontract.go +./bin/neo-go contract opdump -i mycontract.go ``` This will result in something like this: diff --git a/cli/.gitignore b/cli/.gitignore new file mode 100644 index 000000000..573c0c4f2 --- /dev/null +++ b/cli/.gitignore @@ -0,0 +1 @@ +cli diff --git a/cli/main.go b/cli/main.go index 2a5fb679f..e4b3e8fb3 100644 --- a/cli/main.go +++ b/cli/main.go @@ -11,6 +11,7 @@ import ( func main() { ctl := cli.NewApp() ctl.Name = "neo-go" + ctl.Usage = "Official Go client for Neo" ctl.Commands = []cli.Command{ server.NewCommand(), diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 4425d8cb5..7d2010134 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -1,12 +1,14 @@ package smartcontract import ( - "errors" - "github.com/CityOfZion/neo-go/pkg/vm/compiler" "github.com/urfave/cli" ) +const ( + ErrNoInput = "Input file is mandatory and should be passed using -i flag." +) + // NewCommand returns a new contract command. func NewCommand() cli.Command { return cli.Command{ @@ -18,6 +20,10 @@ func NewCommand() cli.Command { Usage: "compile a smart contract to a .avm file", Action: contractCompile, Flags: []cli.Flag{ + cli.StringFlag{ + Name: "in, i", + Usage: "Input file for the smart contract to be compiled", + }, cli.StringFlag{ Name: "out, o", Usage: "Output of the compiled contract", @@ -28,14 +34,21 @@ func NewCommand() cli.Command { Name: "opdump", Usage: "dump the opcode of a .go file", Action: contractDumpOpcode, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "in, i", + Usage: "Input file for the smart contract", + }, + }, }, }, } } func contractCompile(ctx *cli.Context) error { - if len(ctx.Args()) == 0 { - return errors.New("not enough arguments") + src := ctx.String("in") + if len(src) == 0 { + return cli.NewExitError(ErrNoInput, 1) } o := &compiler.Options{ @@ -43,14 +56,19 @@ func contractCompile(ctx *cli.Context) error { Debug: true, } - src := ctx.Args()[0] - return compiler.CompileAndSave(src, o) + if err := compiler.CompileAndSave(src, o); err != nil { + return cli.NewExitError(err, 1) + } + return nil } func contractDumpOpcode(ctx *cli.Context) error { - if len(ctx.Args()) == 0 { - return errors.New("not enough arguments") + src := ctx.String("in") + if len(src) == 0 { + return cli.NewExitError(ErrNoInput, 1) } - src := ctx.Args()[0] - return compiler.DumpOpcode(src) + if err := compiler.DumpOpcode(src); err != nil { + return cli.NewExitError(err, 1) + } + return nil } diff --git a/pkg/vm/compiler/README.md b/pkg/vm/compiler/README.md index 78d02392e..43d3918dc 100644 --- a/pkg/vm/compiler/README.md +++ b/pkg/vm/compiler/README.md @@ -4,6 +4,12 @@ The neo-go compiler compiles Go programs to bytecode that the NEO virtual machin > The neo-go compiler is under very active development and will be updated on a weekly basis. +## Usage + +``` +./bin/neo-go contract compile -i mycontract.go --out /Users/foo/bar/contract.avm +``` + ## Currently supported ### Go internals diff --git a/pkg/vm/compiler/compiler.go b/pkg/vm/compiler/compiler.go index 100b3cfe3..46655b89c 100644 --- a/pkg/vm/compiler/compiler.go +++ b/pkg/vm/compiler/compiler.go @@ -3,7 +3,6 @@ package compiler import ( "bytes" "encoding/hex" - "errors" "fmt" "go/ast" "go/build" @@ -114,10 +113,10 @@ func resolveImports(f *ast.File) (map[string]*archive, error) { // CompileAndSave will compile and save the file to disk. func CompileAndSave(src string, o *Options) error { + if !strings.HasSuffix(src, ".go") { + return fmt.Errorf("%s is not a Go file", src) + } if len(o.Outfile) == 0 { - if !strings.HasSuffix(src, ".go") { - return errors.New("not a Go file") - } o.Outfile = strings.TrimSuffix(src, ".go") } if len(o.Ext) == 0 { @@ -129,7 +128,7 @@ func CompileAndSave(src string, o *Options) error { } b, err = Compile(bytes.NewReader(b), o) if err != nil { - return err + return fmt.Errorf("Error while trying to compile smart contract file: %v", err) } if o.Debug { log.Println(hex.EncodeToString(b))