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
This commit is contained in:
Pawan Rawal 2018-02-24 20:10:45 +11:00 committed by Anthony De Meulemeester
parent 23cfebf621
commit e93dfe8062
6 changed files with 43 additions and 18 deletions

View file

@ -117,20 +117,20 @@ TODO
### Compile a smart contract ### 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: 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 ### Debugging your smart contract
You can dump the opcodes generated by the compiler with the following command: 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: This will result in something like this:

1
cli/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
cli

View file

@ -11,6 +11,7 @@ import (
func main() { func main() {
ctl := cli.NewApp() ctl := cli.NewApp()
ctl.Name = "neo-go" ctl.Name = "neo-go"
ctl.Usage = "Official Go client for Neo"
ctl.Commands = []cli.Command{ ctl.Commands = []cli.Command{
server.NewCommand(), server.NewCommand(),

View file

@ -1,12 +1,14 @@
package smartcontract package smartcontract
import ( import (
"errors"
"github.com/CityOfZion/neo-go/pkg/vm/compiler" "github.com/CityOfZion/neo-go/pkg/vm/compiler"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
const (
ErrNoInput = "Input file is mandatory and should be passed using -i flag."
)
// NewCommand returns a new contract command. // NewCommand returns a new contract command.
func NewCommand() cli.Command { func NewCommand() cli.Command {
return cli.Command{ return cli.Command{
@ -18,6 +20,10 @@ func NewCommand() cli.Command {
Usage: "compile a smart contract to a .avm file", Usage: "compile a smart contract to a .avm file",
Action: contractCompile, Action: contractCompile,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{
Name: "in, i",
Usage: "Input file for the smart contract to be compiled",
},
cli.StringFlag{ cli.StringFlag{
Name: "out, o", Name: "out, o",
Usage: "Output of the compiled contract", Usage: "Output of the compiled contract",
@ -28,14 +34,21 @@ func NewCommand() cli.Command {
Name: "opdump", Name: "opdump",
Usage: "dump the opcode of a .go file", Usage: "dump the opcode of a .go file",
Action: contractDumpOpcode, Action: contractDumpOpcode,
Flags: []cli.Flag{
cli.StringFlag{
Name: "in, i",
Usage: "Input file for the smart contract",
},
},
}, },
}, },
} }
} }
func contractCompile(ctx *cli.Context) error { func contractCompile(ctx *cli.Context) error {
if len(ctx.Args()) == 0 { src := ctx.String("in")
return errors.New("not enough arguments") if len(src) == 0 {
return cli.NewExitError(ErrNoInput, 1)
} }
o := &compiler.Options{ o := &compiler.Options{
@ -43,14 +56,19 @@ func contractCompile(ctx *cli.Context) error {
Debug: true, Debug: true,
} }
src := ctx.Args()[0] if err := compiler.CompileAndSave(src, o); err != nil {
return compiler.CompileAndSave(src, o) return cli.NewExitError(err, 1)
}
return nil
} }
func contractDumpOpcode(ctx *cli.Context) error { func contractDumpOpcode(ctx *cli.Context) error {
if len(ctx.Args()) == 0 { src := ctx.String("in")
return errors.New("not enough arguments") if len(src) == 0 {
return cli.NewExitError(ErrNoInput, 1)
} }
src := ctx.Args()[0] if err := compiler.DumpOpcode(src); err != nil {
return compiler.DumpOpcode(src) return cli.NewExitError(err, 1)
}
return nil
} }

View file

@ -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. > 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 ## Currently supported
### Go internals ### Go internals

View file

@ -3,7 +3,6 @@ package compiler
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"go/ast" "go/ast"
"go/build" "go/build"
@ -114,10 +113,10 @@ func resolveImports(f *ast.File) (map[string]*archive, error) {
// CompileAndSave will compile and save the file to disk. // CompileAndSave will compile and save the file to disk.
func CompileAndSave(src string, o *Options) error { 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 len(o.Outfile) == 0 {
if !strings.HasSuffix(src, ".go") {
return errors.New("not a Go file")
}
o.Outfile = strings.TrimSuffix(src, ".go") o.Outfile = strings.TrimSuffix(src, ".go")
} }
if len(o.Ext) == 0 { if len(o.Ext) == 0 {
@ -129,7 +128,7 @@ func CompileAndSave(src string, o *Options) error {
} }
b, err = Compile(bytes.NewReader(b), o) b, err = Compile(bytes.NewReader(b), o)
if err != nil { if err != nil {
return err return fmt.Errorf("Error while trying to compile smart contract file: %v", err)
} }
if o.Debug { if o.Debug {
log.Println(hex.EncodeToString(b)) log.Println(hex.EncodeToString(b))