返回 DeepSeek-Reasonix
comments_test.go
根目录 / tools / repolint / comments_test.go
1 package main
2
3 import (
4 "strings"
5 "testing"
6 )
7
8 func rules(t *testing.T, rel, src string) []string {
9 t.Helper()
10 s := parseBytes(rel, []byte(src))
11 if s == nil {
12 t.Fatalf("parse %s failed", rel)
13 }
14 var out []string
15 for _, f := range checkComments(s) {
16 out = append(out, f.Rule)
17 }
18 return out
19 }
20
21 func TestCgoPreambleIsCompilerInputNotProse(t *testing.T) {
22 src := "package main\n\n/*\n#include <stdint.h>\n\nstatic void tick(void) {\n\tif (x != NULL) {\n\t\treturn;\n\t}\n\tstart(1);\n}\n*/\nimport \"C\"\n"
23 if got := rules(t, "watchdog.go", src); len(got) != 0 {
24 t.Fatalf("cgo preamble flagged: %v", got)
25 }
26 }
27
28 func TestTrailingCommentIsNotDeadCode(t *testing.T) {
29 src := "package p\n\ntype T struct {\n\tKind string // tool | plan | recovery; empty = tool\n\tSum string // ssh.FingerprintSHA256(key)\n}\n"
30 if got := rules(t, "t.go", src); len(got) != 0 {
31 t.Fatalf("trailing field comments flagged: %v", got)
32 }
33 }
34
35 func TestDocCommentCodeBlockIsNotDeadCode(t *testing.T) {
36 src := "package p\n\n// Run does a thing:\n//\n//\tx := Run(ctx)\nfunc Run() {}\n"
37 if got := rules(t, "t.go", src); len(got) != 0 {
38 t.Fatalf("doc code block flagged: %v", got)
39 }
40 }
41
42 func TestDeclarationDocsAllowDetailedContractsButRemainBounded(t *testing.T) {
43 var doc strings.Builder
44 doc.WriteString("// Run explains a non-obvious contract.\n")
45 for range capDeclDoc - 1 {
46 doc.WriteString("// Additional contract detail.\n")
47 }
48 clean := "package p\n\n" + doc.String() + "func Run() {}\n"
49 if got := rules(t, "t.go", clean); len(got) != 0 {
50 t.Fatalf("%d-line declaration doc flagged: %v", capDeclDoc, got)
51 }
52
53 doc.WriteString("// One line beyond the declaration-doc limit.\n")
54 tooLong := "package p\n\n" + doc.String() + "func Run() {}\n"
55 found := checkComments(parseBytes("t.go", []byte(tooLong)))
56 if len(found) != 1 || found[0].Rule != ruleEssay || found[0].Weight != 1 {
57 t.Fatalf("want one 1-line %s excess, got %+v", ruleEssay, found)
58 }
59 }
60
61 func TestFloatingCommentsKeepTheShortLimit(t *testing.T) {
62 src := "package p\n\nfunc Run() {\n\t// one\n\t// two\n\t// three\n\t// four\n\t_ = 0\n}\n"
63 found := checkComments(parseBytes("t.go", []byte(src)))
64 if len(found) != 1 || found[0].Rule != ruleEssay || found[0].Weight != 1 {
65 t.Fatalf("want one 1-line %s excess, got %+v", ruleEssay, found)
66 }
67 }
68
69 func TestCommentedOutCodeInBodyIsFlagged(t *testing.T) {
70 src := "package p\n\nfunc Run() {\n\t// old := compute(1)\n\t_ = 0\n}\n"
71 if got := rules(t, "t.go", src); len(got) != 1 || got[0] != ruleDeadCode {
72 t.Fatalf("want one %s, got %v", ruleDeadCode, got)
73 }
74 }
75
76 func TestEssayWeightIsTheExcessOverTheLimit(t *testing.T) {
77 src := "package p\n\nfunc Run() {\n\t// one\n\t// two\n\t// three\n\t// four\n\t// five\n\t_ = 0\n}\n"
78 s := parseBytes("t.go", []byte(src))
79 found := checkComments(s)
80 if len(found) != 1 || found[0].Rule != ruleEssay {
81 t.Fatalf("want one %s, got %v", ruleEssay, found)
82 }
83 if found[0].Weight != 5-capFloating {
84 t.Fatalf("weight = %d, want %d", found[0].Weight, 5-capFloating)
85 }
86 }
87
88 func TestDocGoCarriesTheLongPackageExplanation(t *testing.T) {
89 long := "package p\n"
90 var doc strings.Builder
91 doc.WriteString("// Package p explains itself.\n")
92 for range capPackageDoc + 2 {
93 doc.WriteString("//\n// more prose\n")
94 }
95 if got := rules(t, "sub/doc.go", doc.String()+long); len(got) != 0 {
96 t.Fatalf("doc.go package comment flagged: %v", got)
97 }
98 if got := rules(t, "sub/other.go", doc.String()+long); len(got) == 0 {
99 t.Fatal("same package comment outside doc.go should be flagged")
100 }
101 }
102
103 func TestMarkersAndNarrative(t *testing.T) {
104 for _, tc := range []struct {
105 name, comment, want string
106 }{
107 {"bare todo", "// TODO: later", ruleMarker},
108 {"anchored todo", "// TODO(#312): later", ""},
109 {"fixme", "// FIXME later", ruleMarker},
110 {"stage narrative", "// Stage 6b2 hands off the prompt", ruleNarrative},
111 {"lowercase hack prose", "// this is a hack around a driver bug", ""},
112 {"banner", "// ----------------", ruleBanner},
113 {"labelled banner", "// ─── helpers ───", ruleBanner},
114 {"ascii labelled banner", "// ==== setup ====", ruleBanner},
115 {"prose with ellipsis", "// waits for the child... then reaps it", ""},
116 {"prose with a dash", "// clamp to width-1 — Yoga miscounts wrap", ""},
117 {"build directive", "//go:generate stringer -type=T", ""},
118 } {
119 t.Run(tc.name, func(t *testing.T) {
120 got := rules(t, "t.go", "package p\n\n"+tc.comment+"\nfunc Run() {}\n")
121 if tc.want == "" {
122 if len(got) != 0 {
123 t.Fatalf("want clean, got %v", got)
124 }
125 return
126 }
127 if len(got) != 1 || got[0] != tc.want {
128 t.Fatalf("want %s, got %v", tc.want, got)
129 }
130 })
131 }
132 }
133
133 lines GO