mirror of
https://github.com/mgechev/revive.git
synced 2025-11-25 22:12:38 +02:00
struct-tag: add support for asn1 and bson (#49)
This commit is contained in:
@@ -26,6 +26,22 @@ type RangeAllocation struct {
|
|||||||
Data []byte `json:"data,inline"` // MATCH /unknown option 'inline' in JSON tag/
|
Data []byte `json:"data,inline"` // MATCH /unknown option 'inline' in JSON tag/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RangeAllocation struct {
|
||||||
|
metav1.TypeMeta `bson:",minsize"`
|
||||||
|
metav1.ObjectMeta `bson:"metadata,omitempty"`
|
||||||
|
Range string `bson:"range,flow"` // MATCH /unknown option 'flow' in BSON tag/
|
||||||
|
Data []byte `bson:"data,inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestContextSpecificTags2 struct {
|
||||||
|
A int `asn1:"explicit,tag:1"`
|
||||||
|
B int `asn1:"tag:2"`
|
||||||
|
S string `asn1:"tag:0,utf8"`
|
||||||
|
Ints []int `asn1:"set"`
|
||||||
|
Version int `asn1:"optional,explicit,default:0,tag:0"` // MATCH /duplicated tag number 0/
|
||||||
|
Time time.Time `asn1:"explicit,tag:4,other"` // MATCH /unknown option 'other' in ASN1 tag/
|
||||||
|
}
|
||||||
|
|
||||||
type VirtualMachineRelocateSpecDiskLocator struct {
|
type VirtualMachineRelocateSpecDiskLocator struct {
|
||||||
DynamicData
|
DynamicData
|
||||||
|
|
||||||
@@ -33,5 +49,5 @@ type VirtualMachineRelocateSpecDiskLocator struct {
|
|||||||
Datastore ManagedObjectReference `xml:"datastore,chardata,innerxml"`
|
Datastore ManagedObjectReference `xml:"datastore,chardata,innerxml"`
|
||||||
DiskMoveType string `xml:"diskMoveType,omitempty,comment"`
|
DiskMoveType string `xml:"diskMoveType,omitempty,comment"`
|
||||||
DiskBackingInfo BaseVirtualDeviceBackingInfo `xml:"diskBackingInfo,omitempty,any"`
|
DiskBackingInfo BaseVirtualDeviceBackingInfo `xml:"diskBackingInfo,omitempty,any"`
|
||||||
Profile []BaseVirtualMachineProfileSpec `xml:"profile,omitempty,typeattr"` // MATCH /unknown option 'typeattr' in XML tag/
|
Profile []BaseVirtualMachineProfileSpec `xml:"profile,omitempty,other"` // MATCH /unknown option 'other' in XML tag/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ func (r *StructTagRule) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type lintStructTagRule struct {
|
type lintStructTagRule struct {
|
||||||
onFailure func(lint.Failure)
|
onFailure func(lint.Failure)
|
||||||
|
usedTagNbr map[string]bool // list of used tag numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor {
|
func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor {
|
||||||
@@ -42,7 +43,7 @@ func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor {
|
|||||||
if n.Fields == nil || n.Fields.NumFields() < 1 {
|
if n.Fields == nil || n.Fields.NumFields() < 1 {
|
||||||
return nil // skip empty structs
|
return nil // skip empty structs
|
||||||
}
|
}
|
||||||
|
w.usedTagNbr = map[string]bool{} // init
|
||||||
for _, f := range n.Fields.List {
|
for _, f := range n.Fields.List {
|
||||||
if f.Tag != nil {
|
if f.Tag != nil {
|
||||||
w.checkTaggedField(f)
|
w.checkTaggedField(f)
|
||||||
@@ -59,13 +60,22 @@ func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor {
|
|||||||
func (w lintStructTagRule) checkTaggedField(f *ast.Field) {
|
func (w lintStructTagRule) checkTaggedField(f *ast.Field) {
|
||||||
tags, err := structtag.Parse(strings.Trim(f.Tag.Value, "`"))
|
tags, err := structtag.Parse(strings.Trim(f.Tag.Value, "`"))
|
||||||
if err != nil || tags == nil {
|
if err != nil || tags == nil {
|
||||||
|
w.addFailure(f.Tag, "malformed tag")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tag := range tags.Tags() {
|
for _, tag := range tags.Tags() {
|
||||||
switch key := tag.Key; key {
|
switch key := tag.Key; key {
|
||||||
case "asn1":
|
case "asn1":
|
||||||
// Not implemented yet
|
msg, ok := w.checkASN1Tag(f.Type, tag)
|
||||||
|
if !ok {
|
||||||
|
w.addFailure(f.Tag, msg)
|
||||||
|
}
|
||||||
|
case "bson":
|
||||||
|
msg, ok := w.checkBSONTag(tag.Options)
|
||||||
|
if !ok {
|
||||||
|
w.addFailure(f.Tag, msg)
|
||||||
|
}
|
||||||
case "default":
|
case "default":
|
||||||
if !w.typeValueMatch(f.Type, tag.Name) {
|
if !w.typeValueMatch(f.Type, tag.Name) {
|
||||||
w.addFailure(f.Tag, "field's type and default value's type mismatch")
|
w.addFailure(f.Tag, "field's type and default value's type mismatch")
|
||||||
@@ -97,6 +107,55 @@ func (w lintStructTagRule) checkTaggedField(f *ast.Field) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w lintStructTagRule) checkASN1Tag(t ast.Expr, tag *structtag.Tag) (string, bool) {
|
||||||
|
checkList := append(tag.Options, tag.Name)
|
||||||
|
for _, opt := range checkList {
|
||||||
|
switch opt {
|
||||||
|
case "application", "explicit", "generalized", "ia5", "omitempty", "optional", "set", "utf8":
|
||||||
|
|
||||||
|
default:
|
||||||
|
if strings.HasPrefix(opt, "tag:") {
|
||||||
|
parts := strings.Split(opt, ":")
|
||||||
|
tagNumber := parts[1]
|
||||||
|
if w.usedTagNbr[tagNumber] {
|
||||||
|
return fmt.Sprintf("duplicated tag number %s", tagNumber), false
|
||||||
|
}
|
||||||
|
w.usedTagNbr[tagNumber] = true
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(opt, "default:") {
|
||||||
|
parts := strings.Split(opt, ":")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return "malformed default for ASN1 tag", false
|
||||||
|
}
|
||||||
|
if !w.typeValueMatch(t, parts[1]) {
|
||||||
|
return "field's type and default value's type mismatch", false
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("unknown option '%s' in ASN1 tag", opt), false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w lintStructTagRule) checkBSONTag(options []string) (string, bool) {
|
||||||
|
for _, opt := range options {
|
||||||
|
switch opt {
|
||||||
|
case "inline", "minsize", "omitempty":
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown option '%s' in BSON tag", opt), false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", true
|
||||||
|
}
|
||||||
|
|
||||||
func (w lintStructTagRule) checkJSONTag(options []string) (string, bool) {
|
func (w lintStructTagRule) checkJSONTag(options []string) (string, bool) {
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
switch opt {
|
switch opt {
|
||||||
@@ -112,7 +171,7 @@ func (w lintStructTagRule) checkJSONTag(options []string) (string, bool) {
|
|||||||
func (w lintStructTagRule) checkXMLTag(options []string) (string, bool) {
|
func (w lintStructTagRule) checkXMLTag(options []string) (string, bool) {
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
switch opt {
|
switch opt {
|
||||||
case "attr", "cdata", "chardata", "innerxml", "comment", "any", "omitempty":
|
case "any", "attr", "cdata", "chardata", "comment", "innerxml", "omitempty", "typeattr":
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("unknown option '%s' in XML tag", opt), false
|
return fmt.Sprintf("unknown option '%s' in XML tag", opt), false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user