Repository: fatih/gomodifytags
Pull request #53 (2020-01-05 12:00:04)

Add new "skip-private" option
Really we never need JSON tags for private fields
So this is such an option

For example you may have following struct

    type Struct struct {
        Public  int
        private int
    }

Currently gomodifytags would add these tags

    type Struct struct {
        Public  int `json:"public"`
        private int `json:"private"`
    }

With new option it would add

    type Struct struct {
        Public  int `json:"public"`
        private int
    }

fatih: Could you please more specific on what you're trying to do?  You should at least include some new tests and provide a better and readable description in the PR. 
igrmk: I've updated the description and pushed tests
fatih: This looks good 👍  Thank you for working on this @igrmk. 

Patch:
diff --git a/main.go b/main.go
index b370bbe..9703712 100644
--- a/main.go
+++ b/main.go
@@ -18,6 +18,7 @@ import (
 	"sort"
 	"strconv"
 	"strings"
+	"unicode"
 
 	"github.com/fatih/camelcase"
 	"github.com/fatih/structtag"
@@ -56,9 +57,10 @@ type config struct {
 	remove        []string
 	removeOptions []string
 
-	add        []string
-	addOptions []string
-	override   bool
+	add               []string
+	addOptions        []string
+	override          bool
+	skipPrivateFields bool
 
 	transform   string
 	sort        bool
@@ -99,8 +101,9 @@ func realMain() error {
 		flagAddTags = flag.String("add-tags", "",
 			"Adds tags for the comma separated list of keys."+
 				"Keys can contain a static value, i,e: json:foo")
-		flagOverride  = flag.Bool("override", false, "Override current tags when adding tags")
-		flagTransform = flag.String("transform", "snakecase",
+		flagOverride          = flag.Bool("override", false, "Override current tags when adding tags")
+		flagSkipPrivateFields = flag.Bool("skip-private", false, "Skip private fields")
+		flagTransform         = flag.String("transform", "snakecase",
 			"Transform adds a transform rule when adding tags."+
 				" Current options: [snakecase, camelcase, lispcase, pascalcase, keep]")
 		flagSort = flag.Bool("sort", false,
@@ -127,17 +130,18 @@ func realMain() error {
 	}
 
 	cfg := &config{
-		file:        *flagFile,
-		line:        *flagLine,
-		structName:  *flagStruct,
-		offset:      *flagOffset,
-		output:      *flagOutput,
-		write:       *flagWrite,
-		clear:       *flagClearTags,
-		clearOption: *flagClearOptions,
-		transform:   *flagTransform,
-		sort:        *flagSort,
-		override:    *flagOverride,
+		file:              *flagFile,
+		line:              *flagLine,
+		structName:        *flagStruct,
+		offset:            *flagOffset,
+		output:            *flagOutput,
+		write:             *flagWrite,
+		clear:             *flagClearTags,
+		clearOption:       *flagClearOptions,
+		transform:         *flagTransform,
+		sort:              *flagSort,
+		override:          *flagOverride,
+		skipPrivateFields: *flagSkipPrivateFields,
 	}
 
 	if *flagModified {
@@ -599,6 +603,13 @@ func (c *config) offsetSelection(file ast.Node) (int, int, error) {
 	return start, end, nil
 }
 
+func isPublicName(name string) bool {
+	for _, c := range name {
+		return unicode.IsUpper(c)
+	}
+	return false
+}
+
 // rewrite rewrites the node for structs between the start and end
 // positions
 func (c *config) rewrite(node ast.Node, start, end int) (ast.Node, error) {
@@ -617,13 +628,19 @@ func (c *config) rewrite(node ast.Node, start, end int) (ast.Node, error) {
 				continue
 			}
 
-			if f.Tag == nil {
-				f.Tag = &ast.BasicLit{}
-			}
-
 			fieldName := ""
 			if len(f.Names) != 0 {
-				fieldName = f.Names[0].Name
+				for _, field := range f.Names {
+					if !c.skipPrivateFields || isPublicName(field.Name) {
+						fieldName = field.Name
+						break
+					}
+				}
+
+				// nothing to process, continue with next line
+				if fieldName == "" {
+					continue
+				}
 			}
 
 			// anonymous field
@@ -636,6 +653,10 @@ func (c *config) rewrite(node ast.Node, start, end int) (ast.Node, error) {
 				fieldName = ident.Name
 			}
 
+			if f.Tag == nil {
+				f.Tag = &ast.BasicLit{}
+			}
+
 			res, err := c.process(fieldName, f.Tag.Value)
 			if err != nil {
 				errs.Append(fmt.Errorf("%s:%d:%d:%s",


Test patch:
diff --git a/main_test.go b/main_test.go
index 474996f..8bae635 100644
--- a/main_test.go
+++ b/main_test.go
@@ -313,6 +313,26 @@ func TestRewrite(t *testing.T) {
 				transform: "snakecase",
 			},
 		},
+		{
+			file: "skip_private",
+			cfg: &config{
+				add:               []string{"json"},
+				output:            "source",
+				structName:        "foo",
+				transform:         "snakecase",
+				skipPrivateFields: true,
+			},
+		},
+		{
+			file: "skip_private_multiple_names",
+			cfg: &config{
+				add:               []string{"json"},
+				output:            "source",
+				structName:        "foo",
+				transform:         "snakecase",
+				skipPrivateFields: true,
+			},
+		},
 	}
 
 	for _, ts := range test {
diff --git a/test-fixtures/skip_private.golden b/test-fixtures/skip_private.golden
new file mode 100644
index 0000000..c6f4570
--- /dev/null
+++ b/test-fixtures/skip_private.golden
@@ -0,0 +1,6 @@
+package foo
+
+type foo struct {
+	Bar string `json:"bar"`
+	t   bool
+}
diff --git a/test-fixtures/skip_private.input b/test-fixtures/skip_private.input
new file mode 100644
index 0000000..121932c
--- /dev/null
+++ b/test-fixtures/skip_private.input
@@ -0,0 +1,6 @@
+package foo
+
+type foo struct {
+	Bar string
+	t   bool
+}
diff --git a/test-fixtures/skip_private_multiple_names.golden b/test-fixtures/skip_private_multiple_names.golden
new file mode 100644
index 0000000..3fd2eaf
--- /dev/null
+++ b/test-fixtures/skip_private_multiple_names.golden
@@ -0,0 +1,6 @@
+package foo
+
+type foo struct {
+	Bar    string `json:"bar"`
+	t, Baz bool   `json:"baz"`
+}
diff --git a/test-fixtures/skip_private_multiple_names.input b/test-fixtures/skip_private_multiple_names.input
new file mode 100644
index 0000000..66a4d73
--- /dev/null
+++ b/test-fixtures/skip_private_multiple_names.input
@@ -0,0 +1,6 @@
+package foo
+
+type foo struct {
+	Bar    string
+	t, Baz bool
+}