Skip to content

Commit

Permalink
cmd/abigen: extend --exc to accept globs
Browse files Browse the repository at this point in the history
The --exc flag now supports glob matching of the form
"path/to/file.sol:*" and "*:Type".
  • Loading branch information
sebastianst authored and holiman committed Sep 23, 2022
1 parent ffc6fc2 commit 2d4351f
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 4 deletions.
8 changes: 4 additions & 4 deletions cmd/abigen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ func abigen(c *cli.Context) error {
types = append(types, kind)
} else {
// Generate the list of types to exclude from binding
exclude := make(map[string]bool)
for _, kind := range strings.Split(c.String(excFlag.Name), ",") {
exclude[strings.ToLower(kind)] = true
exclude, err := newNameFilter(strings.Split(c.String(excFlag.Name), ",")...)
if err != nil {
utils.Fatalf("Failed to parse excludes: %v", err)
}
var contracts map[string]*compiler.Contract

Expand Down Expand Up @@ -184,7 +184,7 @@ func abigen(c *cli.Context) error {
// fully qualified name is of the form <solFilePath>:<type>
nameParts := strings.Split(name, ":")
typeName := nameParts[len(nameParts)-1]
if exclude[strings.ToLower(typeName)] {
if exclude.Matches(name) {
continue
}
abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
Expand Down
58 changes: 58 additions & 0 deletions cmd/abigen/namefilter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"fmt"
"strings"
)

type nameFilter struct {
fulls map[string]bool // path/to/contract.sol:Type
files map[string]bool // path/to/contract.sol:*
types map[string]bool // *:Type
}

func newNameFilter(patterns ...string) (*nameFilter, error) {
f := &nameFilter{
fulls: make(map[string]bool),
files: make(map[string]bool),
types: make(map[string]bool),
}
for _, pattern := range patterns {
if err := f.add(pattern); err != nil {
return nil, err
}
}
return f, nil
}

func (f *nameFilter) add(pattern string) error {
ft := strings.Split(pattern, ":")
if len(ft) != 2 {
// filenames and types must not include ':' symbol
return fmt.Errorf("invalid pattern: %s", pattern)
}

file, typ := ft[0], ft[1]
if file == "*" {
f.types[typ] = true
return nil
} else if typ == "*" {
f.files[file] = true
return nil
}
f.fulls[pattern] = true
return nil
}

func (f *nameFilter) Matches(name string) bool {
ft := strings.Split(name, ":")
if len(ft) != 2 {
// If contract names are always of the fully-qualified form
// <filePath>:<type>, then this case will never happen.
return false
}

file, typ := ft[0], ft[1]
// full paths > file paths > types
return f.fulls[name] || f.files[file] || f.types[typ]
}
38 changes: 38 additions & 0 deletions cmd/abigen/namefilter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNameFilter(t *testing.T) {
_, err := newNameFilter("Foo")
require.Error(t, err)
_, err = newNameFilter("too/many:colons:Foo")
require.Error(t, err)

f, err := newNameFilter("a/path:A", "*:B", "c/path:*")
require.NoError(t, err)

for _, tt := range []struct {
name string
match bool
}{
{"a/path:A", true},
{"unknown/path:A", false},
{"a/path:X", false},
{"unknown/path:X", false},
{"any/path:B", true},
{"c/path:X", true},
{"c/path:foo:B", false},
} {
match := f.Matches(tt.name)
if tt.match {
assert.True(t, match, "expected match")
} else {
assert.False(t, match, "expected no match")
}
}
}

0 comments on commit 2d4351f

Please sign in to comment.