compiler: restore event check warnings

It was broken after changes for inlining. Add tests.
This commit is contained in:
Evgeniy Stratonikov 2021-06-02 11:46:08 +03:00
parent f33daf759a
commit 1a5e656d38
3 changed files with 68 additions and 14 deletions

View file

@ -959,20 +959,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
ast.Walk(c, n.Fun)
emit.Opcodes(c.prog.BinWriter, opcode.CALLA)
case isSyscall(f):
if f.pkg.Name() == "runtime" && f.name == "Notify" {
tv := c.typeAndValueOf(n.Args[0])
params := make([]string, 0, len(n.Args[1:]))
for _, p := range n.Args[1:] {
st, _ := c.scAndVMTypeFromExpr(p)
params = append(params, st.String())
}
// Sometimes event name is stored in a var.
// Skip in this case.
if tv.Value != nil {
name := constant.StringVal(tv.Value)
c.emittedEvents[name] = append(c.emittedEvents[name], params)
}
}
c.convertSyscall(f, n)
default:
emit.Call(c.prog.BinWriter, opcode.CALLL, f.label)

View file

@ -9,6 +9,8 @@ import (
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/stretchr/testify/require"
)
@ -130,3 +132,46 @@ func TestOnPayableChecks(t *testing.T) {
require.Error(t, compileAndCheck(t, src))
})
}
func TestEventWarnings(t *testing.T) {
src := `package payable
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
func Main() { runtime.Notify("Event", 1) }`
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src))
require.NoError(t, err)
t.Run("event it missing from config", func(t *testing.T) {
_, err = compiler.CreateManifest(di, &compiler.Options{})
require.Error(t, err)
t.Run("suppress", func(t *testing.T) {
_, err = compiler.CreateManifest(di, &compiler.Options{NoEventsCheck: true})
require.NoError(t, err)
})
})
t.Run("wrong parameter number", func(t *testing.T) {
_, err = compiler.CreateManifest(di, &compiler.Options{
ContractEvents: []manifest.Event{{Name: "Event"}},
})
require.Error(t, err)
})
t.Run("wrong parameter type", func(t *testing.T) {
_, err = compiler.CreateManifest(di, &compiler.Options{
ContractEvents: []manifest.Event{{
Name: "Event",
Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.StringType)},
}},
})
require.Error(t, err)
})
t.Run("good", func(t *testing.T) {
_, err = compiler.CreateManifest(di, &compiler.Options{
ContractEvents: []manifest.Event{{
Name: "Event",
Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.IntegerType)},
}},
})
require.NoError(t, err)
})
}

View file

@ -2,6 +2,7 @@ package compiler
import (
"go/ast"
"go/constant"
"go/types"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
@ -27,6 +28,8 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
pkg := c.buildInfo.program.Package(f.pkg.Path())
sig := c.typeOf(n.Fun).(*types.Signature)
c.processNotify(f, n.Args)
// When inlined call is used during global initialization
// there is no func scope, thus this if.
if c.scope == nil {
@ -114,3 +117,23 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
c.importMap = oldMap
c.pkgInfoInline = c.pkgInfoInline[:len(c.pkgInfoInline)-1]
}
func (c *codegen) processNotify(f *funcScope, args []ast.Expr) {
if f != nil && f.pkg.Path() == interopPrefix+"/runtime" && f.name == "Notify" {
// Sometimes event name is stored in a var.
// Skip in this case.
tv := c.typeAndValueOf(args[0])
if tv.Value == nil {
return
}
params := make([]string, 0, len(args[1:]))
for _, p := range args[1:] {
st, _ := c.scAndVMTypeFromExpr(p)
params = append(params, st.String())
}
name := constant.StringVal(tv.Value)
c.emittedEvents[name] = append(c.emittedEvents[name], params)
}
}