Skip to content

Commit 5a550b6

Browse files
committed
go/ast: drop //directive comments from doc.Text
This allows writing // F does a thing. //go:noinline func F() without the //go:noinline or other directive (such as //line) ending up looking like extra words in the doc comment. Fixes #37974. Change-Id: Ic738d72802cc2fa448f7633915e7126d2f76d8ca Reviewed-on: https://go-review.googlesource.com/c/go/+/224737 Reviewed-by: Robert Griesemer <[email protected]>
1 parent b13ce66 commit 5a550b6

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

src/go/ast/ast.go

+41-6
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ func stripTrailingWhitespace(s string) string {
8787

8888
// Text returns the text of the comment.
8989
// Comment markers (//, /*, and */), the first space of a line comment, and
90-
// leading and trailing empty lines are removed. Multiple empty lines are
91-
// reduced to one, and trailing space on lines is trimmed. Unless the result
92-
// is empty, it is newline-terminated.
93-
//
90+
// leading and trailing empty lines are removed.
91+
// Comment directives like "//line" and "//go:noinline" are also removed.
92+
// Multiple empty lines are reduced to one, and trailing space on lines is trimmed.
93+
// Unless the result is empty, it is newline-terminated.
9494
func (g *CommentGroup) Text() string {
9595
if g == nil {
9696
return ""
@@ -108,9 +108,18 @@ func (g *CommentGroup) Text() string {
108108
case '/':
109109
//-style comment (no newline at the end)
110110
c = c[2:]
111-
// strip first space - required for Example tests
112-
if len(c) > 0 && c[0] == ' ' {
111+
if len(c) == 0 {
112+
// empty line
113+
break
114+
}
115+
if c[0] == ' ' {
116+
// strip first space - required for Example tests
113117
c = c[1:]
118+
break
119+
}
120+
if isDirective(c) {
121+
// Ignore //go:noinline, //line, and so on.
122+
continue
114123
}
115124
case '*':
116125
/*-style comment */
@@ -145,6 +154,32 @@ func (g *CommentGroup) Text() string {
145154
return strings.Join(lines, "\n")
146155
}
147156

157+
// isDirective reports whether c is a comment directive.
158+
func isDirective(c string) bool {
159+
// "//line " is a line directive.
160+
// (The // has been removed.)
161+
if strings.HasPrefix(c, "line ") {
162+
return true
163+
}
164+
165+
// "//[a-z0-9]+:[a-z0-9]"
166+
// (The // has been removed.)
167+
colon := strings.Index(c, ":")
168+
if colon <= 0 || colon+1 >= len(c) {
169+
return false
170+
}
171+
for i := 0; i <= colon+1; i++ {
172+
if i == colon {
173+
continue
174+
}
175+
b := c[i]
176+
if !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {
177+
return false
178+
}
179+
}
180+
return true
181+
}
182+
148183
// ----------------------------------------------------------------------------
149184
// Expressions and types
150185

src/go/ast/ast_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ var comments = []struct {
3333
{[]string{"/* Foo*/", "/*\n*/", "//", "/*\n*/", "// Bar"}, " Foo\n\nBar\n"},
3434
{[]string{"/* Foo*/", "// Bar"}, " Foo\nBar\n"},
3535
{[]string{"/* Foo\n Bar*/"}, " Foo\n Bar\n"},
36+
37+
{[]string{"// foo", "//go:noinline", "// bar", "//:baz"}, "foo\nbar\n:baz\n"},
38+
{[]string{"// foo", "//lint123:ignore", "// bar"}, "foo\nbar\n"},
3639
}
3740

3841
func TestCommentText(t *testing.T) {
@@ -48,3 +51,29 @@ func TestCommentText(t *testing.T) {
4851
}
4952
}
5053
}
54+
55+
var isDirectiveTests = []struct {
56+
in string
57+
ok bool
58+
}{
59+
{"abc", false},
60+
{"go:inline", true},
61+
{"Go:inline", false},
62+
{"go:Inline", false},
63+
{":inline", false},
64+
{"lint:ignore", true},
65+
{"lint:1234", true},
66+
{"1234:lint", true},
67+
{"go: inline", false},
68+
{"go:", false},
69+
{"go:*", false},
70+
{"go:x*", true},
71+
}
72+
73+
func TestIsDirective(t *testing.T) {
74+
for _, tt := range isDirectiveTests {
75+
if ok := isDirective(tt.in); ok != tt.ok {
76+
t.Errorf("isDirective(%q) = %v, want %v", tt.in, ok, tt.ok)
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)