go/analysis/passes/structtag: ignore warning if tag should be ignored

Having a private field with a json tag does not necessary means the
field needs to be exposed publicly. This change ignores the warning of
such fields that contain a json tag with the field tag "-".

The lines added in the unit tests will fail without these changes with
the error:
```
a/a.go:36:2: unexpected diagnostic: struct field b has json tag but is not exported
```

Change-Id: Ife987b99c264ae3b60a702e43a1f9c778f8c2d62
Reviewed-on: https://go-review.googlesource.com/c/tools/+/245857
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/go/analysis/passes/structtag/structtag.go b/go/analysis/passes/structtag/structtag.go
index e091603..f0b1505 100644
--- a/go/analysis/passes/structtag/structtag.go
+++ b/go/analysis/passes/structtag/structtag.go
@@ -116,7 +116,11 @@
 	}
 
 	for _, enc := range [...]string{"json", "xml"} {
-		if reflect.StructTag(tag).Get(enc) != "" {
+		switch reflect.StructTag(tag).Get(enc) {
+		// Ignore warning if the field not exported and the tag is marked as
+		// ignored.
+		case "", "-":
+		default:
 			pass.Reportf(field.Pos(), "struct field %s has %s tag but is not exported", field.Name(), enc)
 			return
 		}
diff --git a/go/analysis/passes/structtag/testdata/src/a/a.go b/go/analysis/passes/structtag/testdata/src/a/a.go
index 3394f4c..8b1cea1 100644
--- a/go/analysis/passes/structtag/testdata/src/a/a.go
+++ b/go/analysis/passes/structtag/testdata/src/a/a.go
@@ -33,6 +33,8 @@
 	y int `xml:"yy"`  // want "struct field y has xml tag but is not exported"
 	z int
 	A int `json:"aa" xml:"bb"`
+	b int `json:"-"`
+	C int `json:"-"`
 }
 
 type unexp struct{}
@@ -62,40 +64,40 @@
 
 type DuplicateJSONFields struct {
 	JSON              int `json:"a"`
-	DuplicateJSON     int `json:"a"` // want "struct field DuplicateJSON repeats json tag .a. also at a.go:64"
+	DuplicateJSON     int `json:"a"` // want "struct field DuplicateJSON repeats json tag .a. also at a.go:66"
 	IgnoredJSON       int `json:"-"`
 	OtherIgnoredJSON  int `json:"-"`
 	OmitJSON          int `json:",omitempty"`
 	OtherOmitJSON     int `json:",omitempty"`
-	DuplicateOmitJSON int `json:"a,omitempty"` // want "struct field DuplicateOmitJSON repeats json tag .a. also at a.go:64"
+	DuplicateOmitJSON int `json:"a,omitempty"` // want "struct field DuplicateOmitJSON repeats json tag .a. also at a.go:66"
 	NonJSON           int `foo:"a"`
 	DuplicateNonJSON  int `foo:"a"`
 	Embedded          struct {
 		DuplicateJSON int `json:"a"` // OK because it's not in the same struct type
 	}
-	AnonymousJSON `json:"a"` // want "struct field AnonymousJSON repeats json tag .a. also at a.go:64"
+	AnonymousJSON `json:"a"` // want "struct field AnonymousJSON repeats json tag .a. also at a.go:66"
 
 	XML              int `xml:"a"`
-	DuplicateXML     int `xml:"a"` // want "struct field DuplicateXML repeats xml tag .a. also at a.go:78"
+	DuplicateXML     int `xml:"a"` // want "struct field DuplicateXML repeats xml tag .a. also at a.go:80"
 	IgnoredXML       int `xml:"-"`
 	OtherIgnoredXML  int `xml:"-"`
 	OmitXML          int `xml:",omitempty"`
 	OtherOmitXML     int `xml:",omitempty"`
-	DuplicateOmitXML int `xml:"a,omitempty"` // want "struct field DuplicateOmitXML repeats xml tag .a. also at a.go:78"
+	DuplicateOmitXML int `xml:"a,omitempty"` // want "struct field DuplicateOmitXML repeats xml tag .a. also at a.go:80"
 	NonXML           int `foo:"a"`
 	DuplicateNonXML  int `foo:"a"`
 	Embedded2        struct {
 		DuplicateXML int `xml:"a"` // OK because it's not in the same struct type
 	}
-	AnonymousXML `xml:"a"` // want "struct field AnonymousXML repeats xml tag .a. also at a.go:78"
+	AnonymousXML `xml:"a"` // want "struct field AnonymousXML repeats xml tag .a. also at a.go:80"
 	Attribute    struct {
 		XMLName     xml.Name `xml:"b"`
 		NoDup       int      `xml:"b"`                // OK because XMLName above affects enclosing struct.
 		Attr        int      `xml:"b,attr"`           // OK because <b b="0"><b>0</b></b> is valid.
-		DupAttr     int      `xml:"b,attr"`           // want "struct field DupAttr repeats xml attribute tag .b. also at a.go:94"
-		DupOmitAttr int      `xml:"b,omitempty,attr"` // want "struct field DupOmitAttr repeats xml attribute tag .b. also at a.go:94"
+		DupAttr     int      `xml:"b,attr"`           // want "struct field DupAttr repeats xml attribute tag .b. also at a.go:96"
+		DupOmitAttr int      `xml:"b,omitempty,attr"` // want "struct field DupOmitAttr repeats xml attribute tag .b. also at a.go:96"
 
-		AnonymousXML `xml:"b,attr"` // want "struct field AnonymousXML repeats xml attribute tag .b. also at a.go:94"
+		AnonymousXML `xml:"b,attr"` // want "struct field AnonymousXML repeats xml attribute tag .b. also at a.go:96"
 	}
 
 	AnonymousJSONField2 `json:"not_anon"` // ok; fields aren't embedded in JSON