Repository: google/go-flow-levee
Pull request #5 (2020-05-08 19:18:16)

Extract regex unmarshaller into a separate package.
Extract regex unmarshaller into a separate package.


Patch:
diff --git a/internal/levee.go b/internal/levee.go
index 6946bf0..32f1d1d 100644
--- a/internal/levee.go
+++ b/internal/levee.go
@@ -19,7 +19,6 @@ import (
 	"fmt"
 	"go/types"
 	"io/ioutil"
-	"regexp"
 	"strings"
 	"sync"
 
@@ -29,6 +28,7 @@ import (
 
 	"github.com/eapache/queue"
 
+	"google.com/go-flow-levee/internal/pkg/config/regexp"
 	"google.com/go-flow-levee/internal/pkg/sanitizer"
 )
 
@@ -211,9 +211,9 @@ func (c config) isInScope(pkg *types.Package) bool {
 // Within a given type, specific field access can be specified as the actual source data
 // via the fieldRE.
 type sourceMatcher struct {
-	PackageRE configRegexp
-	TypeRE    configRegexp
-	FieldRE   configRegexp
+	PackageRE regexp.Regexp
+	TypeRE    regexp.Regexp
+	FieldRE   regexp.Regexp
 }
 
 func (s sourceMatcher) match(n *types.Named) bool {
@@ -227,7 +227,7 @@ func (s sourceMatcher) match(n *types.Named) bool {
 
 type fieldPropagatorMatcher struct {
 	Receiver   string
-	AccessorRE configRegexp
+	AccessorRE regexp.Regexp
 }
 
 func (f fieldPropagatorMatcher) match(call *ssa.Call) bool {
@@ -249,7 +249,7 @@ func (f fieldPropagatorMatcher) match(call *ssa.Call) bool {
 
 type transformingPropagatorMatcher struct {
 	PackageName string
-	MethodRE    configRegexp
+	MethodRE    regexp.Regexp
 }
 
 func (t transformingPropagatorMatcher) match(call *ssa.Call) bool {
@@ -263,44 +263,21 @@ func (t transformingPropagatorMatcher) match(call *ssa.Call) bool {
 }
 
 type argumentPropagatorMatcher struct {
-	ArgumentTypeRE configRegexp
+	ArgumentTypeRE regexp.Regexp
 }
 
 type packageMatcher struct {
-	PackageNameRE configRegexp
+	PackageNameRE regexp.Regexp
 }
 
 func (pm packageMatcher) match(pkg *types.Package) bool {
 	return pm.PackageNameRE.MatchString(pkg.Path())
 }
 
-// configRegexp delegates to a Regexp while enabling unmarshalling.
-// Any unspecified / nil matcher will return vacuous truth in MatchString
-type configRegexp struct {
-	r *regexp.Regexp
-}
-
-func (mr *configRegexp) MatchString(s string) bool {
-	return mr.r == nil || mr.r.MatchString(s)
-}
-
-func (mr *configRegexp) UnmarshalJSON(data []byte) error {
-	var matcher string
-	if err := json.Unmarshal(data, &matcher); err != nil {
-		return err
-	}
-
-	var err error
-	if mr.r, err = regexp.Compile(matcher); err != nil {
-		return err
-	}
-	return nil
-}
-
 type nameMatcher struct {
-	PackageRE configRegexp
-	TypeRE    configRegexp
-	MethodRE  configRegexp
+	PackageRE regexp.Regexp
+	TypeRE    regexp.Regexp
+	MethodRE  regexp.Regexp
 }
 
 func (r nameMatcher) matchPackage(p *types.Package) bool {
diff --git a/internal/pkg/config/regexp/regexp.go b/internal/pkg/config/regexp/regexp.go
new file mode 100644
index 0000000..54a84a8
--- /dev/null
+++ b/internal/pkg/config/regexp/regexp.go
@@ -0,0 +1,46 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package regexp contains functionality for unmarshalling regular expressions from a config.
+package regexp
+
+import (
+	"encoding/json"
+	"regexp"
+)
+
+// Regexp delegates to a Regexp while enabling unmarshalling.
+// Any unspecified / nil matcher will return vacuous truth in MatchString
+type Regexp struct {
+	r *regexp.Regexp
+}
+
+// MatchString delegates matching to the regex package.
+func (mr *Regexp) MatchString(s string) bool {
+	return mr.r == nil || mr.r.MatchString(s)
+}
+
+// UnmarshalJSON implementation of json.UnmarshalJSON interface.
+func (mr *Regexp) UnmarshalJSON(data []byte) error {
+	var matcher string
+	if err := json.Unmarshal(data, &matcher); err != nil {
+		return err
+	}
+
+	var err error
+	if mr.r, err = regexp.Compile(matcher); err != nil {
+		return err
+	}
+	return nil
+}


Test patch:
diff --git a/internal/pkg/config/regexp/regexp_test.go b/internal/pkg/config/regexp/regexp_test.go
new file mode 100644
index 0000000..803ca0d
--- /dev/null
+++ b/internal/pkg/config/regexp/regexp_test.go
@@ -0,0 +1,60 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package regexp
+
+import (
+	"encoding/json"
+	"testing"
+)
+
+func TestFlagParser(t *testing.T) {
+	testCases := []struct {
+		desc      string
+		in        []byte
+		wantMatch string
+		wantErr   bool
+	}{
+		{
+			desc:      "valid regex",
+			in:        []byte(`"^hello$"`),
+			wantMatch: "hello",
+		},
+		{
+			desc:    "empty regex",
+			in:      []byte(""),
+			wantErr: true,
+		},
+		{
+			desc:    "invalid regex",
+			in:      []byte("["),
+			wantErr: true,
+		},
+	}
+
+	for _, tt := range testCases {
+		t.Run(tt.desc, func(t *testing.T) {
+			got := &Regexp{}
+			err := json.Unmarshal(tt.in, &got)
+
+			if tt.wantErr && err == nil {
+				t.Fatalf("Got nil, wanted error %v", tt.wantErr)
+			}
+
+			if !got.MatchString(tt.wantMatch) {
+				t.Fatalf("Got false, wanted true for got.MatchStrng(%s)", tt.wantMatch)
+			}
+		})
+	}
+}