github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/fieldsHaveCommentRule.go (about)

     1  package rules
     2  
     3  import (
     4  	"github.com/yoheimuta/go-protoparser/v4/parser"
     5  
     6  	"github.com/yoheimuta/protolint/linter/report"
     7  	"github.com/yoheimuta/protolint/linter/rule"
     8  	"github.com/yoheimuta/protolint/linter/visitor"
     9  )
    10  
    11  // FieldsHaveCommentRule verifies that all fields have a comment.
    12  type FieldsHaveCommentRule struct {
    13  	RuleWithSeverity
    14  	// Golang style comments should begin with the name of the thing being described.
    15  	// See https://github.com/golang/go/wiki/CodeReviewComments#comment-sentences
    16  	shouldFollowGolangStyle bool
    17  }
    18  
    19  // NewFieldsHaveCommentRule creates a new FieldsHaveCommentRule.
    20  func NewFieldsHaveCommentRule(
    21  	severity rule.Severity,
    22  	shouldFollowGolangStyle bool,
    23  ) FieldsHaveCommentRule {
    24  	return FieldsHaveCommentRule{
    25  		RuleWithSeverity:        RuleWithSeverity{severity: severity},
    26  		shouldFollowGolangStyle: shouldFollowGolangStyle,
    27  	}
    28  }
    29  
    30  // ID returns the ID of this rule.
    31  func (r FieldsHaveCommentRule) ID() string {
    32  	return "FIELDS_HAVE_COMMENT"
    33  }
    34  
    35  // Purpose returns the purpose of this rule.
    36  func (r FieldsHaveCommentRule) Purpose() string {
    37  	return "Verifies that all fields have a comment."
    38  }
    39  
    40  // IsOfficial decides whether or not this rule belongs to the official guide.
    41  func (r FieldsHaveCommentRule) IsOfficial() bool {
    42  	return false
    43  }
    44  
    45  // Apply applies the rule to the proto.
    46  func (r FieldsHaveCommentRule) Apply(proto *parser.Proto) ([]report.Failure, error) {
    47  	v := &fieldsHaveCommentVisitor{
    48  		BaseAddVisitor:          visitor.NewBaseAddVisitor(r.ID(), string(r.Severity())),
    49  		shouldFollowGolangStyle: r.shouldFollowGolangStyle,
    50  	}
    51  	return visitor.RunVisitor(v, proto, r.ID())
    52  }
    53  
    54  type fieldsHaveCommentVisitor struct {
    55  	*visitor.BaseAddVisitor
    56  	shouldFollowGolangStyle bool
    57  }
    58  
    59  // VisitField checks the field.
    60  func (v *fieldsHaveCommentVisitor) VisitField(field *parser.Field) bool {
    61  	n := field.FieldName
    62  	if v.shouldFollowGolangStyle && !hasGolangStyleComment(field.Comments, n) {
    63  		v.AddFailuref(field.Meta.Pos, `Field %q should have a comment of the form "// %s ..."`, n, n)
    64  	} else if !hasComments(field.Comments, field.InlineComment) {
    65  		v.AddFailuref(field.Meta.Pos, `Field %q should have a comment`, n)
    66  	}
    67  	return false
    68  }
    69  
    70  // VisitMapField checks the map field.
    71  func (v *fieldsHaveCommentVisitor) VisitMapField(field *parser.MapField) bool {
    72  	n := field.MapName
    73  	if v.shouldFollowGolangStyle && !hasGolangStyleComment(field.Comments, n) {
    74  		v.AddFailuref(field.Meta.Pos, `Field %q should have a comment of the form "// %s ..."`, n, n)
    75  	} else if !hasComments(field.Comments, field.InlineComment) {
    76  		v.AddFailuref(field.Meta.Pos, `Field %q should have a comment`, n)
    77  	}
    78  	return false
    79  }
    80  
    81  // VisitOneofField checks the oneof field.
    82  func (v *fieldsHaveCommentVisitor) VisitOneofField(field *parser.OneofField) bool {
    83  	n := field.FieldName
    84  	if v.shouldFollowGolangStyle && !hasGolangStyleComment(field.Comments, n) {
    85  		v.AddFailuref(field.Meta.Pos, `Field %q should have a comment of the form "// %s ..."`, n, n)
    86  	} else if !hasComments(field.Comments, field.InlineComment) {
    87  		v.AddFailuref(field.Meta.Pos, `Field %q should have a comment`, n)
    88  	}
    89  	return false
    90  }