src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

st1000.go (2258B)


      1 package st1000
      2 
      3 import (
      4 	"fmt"
      5 	"go/ast"
      6 	"strings"
      7 
      8 	"honnef.co/go/tools/analysis/code"
      9 	"honnef.co/go/tools/analysis/lint"
     10 	"honnef.co/go/tools/analysis/report"
     11 
     12 	"golang.org/x/tools/go/analysis"
     13 )
     14 
     15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     16 	Analyzer: &analysis.Analyzer{
     17 		Name: "ST1000",
     18 		Run:  run,
     19 	},
     20 	Doc: &lint.RawDocumentation{
     21 		Title: `Incorrect or missing package comment`,
     22 		Text: `Packages must have a package comment that is formatted according to
     23 the guidelines laid out in
     24 https://go.dev/wiki/CodeReviewComments#package-comments.`,
     25 		Since:      "2019.1",
     26 		NonDefault: true,
     27 		MergeIf:    lint.MergeIfAny,
     28 	},
     29 })
     30 
     31 var Analyzer = SCAnalyzer.Analyzer
     32 
     33 func run(pass *analysis.Pass) (any, error) {
     34 	// - At least one file in a non-main package should have a package comment
     35 	//
     36 	// - The comment should be of the form
     37 	// "Package x ...". This has a slight potential for false
     38 	// positives, as multiple files can have package comments, in
     39 	// which case they get appended. But that doesn't happen a lot in
     40 	// the real world.
     41 
     42 	if pass.Pkg.Name() == "main" {
     43 		return nil, nil
     44 	}
     45 	hasDocs := false
     46 	for _, f := range pass.Files {
     47 		if code.IsInTest(pass, f) {
     48 			continue
     49 		}
     50 		text, ok := docText(f.Doc)
     51 		if ok {
     52 			hasDocs = true
     53 			prefix := "Package " + f.Name.Name
     54 			isNonAlpha := func(b byte) bool {
     55 				// This check only considers ASCII, which can lead to false negatives for some malformed package
     56 				// comments.
     57 				return !((b >= '0' && b <= '9') || (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z'))
     58 			}
     59 			if !strings.HasPrefix(text, prefix) || (len(text) > len(prefix) && !isNonAlpha(text[len(prefix)])) {
     60 				report.Report(pass, f.Doc, fmt.Sprintf(`package comment should be of the form "%s..."`, prefix))
     61 			}
     62 		}
     63 	}
     64 
     65 	if !hasDocs {
     66 		for _, f := range pass.Files {
     67 			if code.IsInTest(pass, f) {
     68 				continue
     69 			}
     70 			report.Report(pass, f, "at least one file in a package should have a package comment", report.ShortRange())
     71 		}
     72 	}
     73 	return nil, nil
     74 }
     75 
     76 func docText(doc *ast.CommentGroup) (string, bool) {
     77 	if doc == nil {
     78 		return "", false
     79 	}
     80 	// We trim spaces primarily because of /**/ style comments, which often have leading space.
     81 	text := strings.TrimSpace(doc.Text())
     82 	return text, text != ""
     83 }