Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: x/tools/cmd/godoc: strip directly-attached compiler directives #47336

Closed
jpap opened this issue Jul 22, 2021 · 2 comments
Closed

proposal: x/tools/cmd/godoc: strip directly-attached compiler directives #47336

jpap opened this issue Jul 22, 2021 · 2 comments

Comments

@jpap
Copy link
Contributor

jpap commented Jul 22, 2021

Background

The Compiler Directives documentation describes how //go:XXX compiler directives should be structured. It leaves ambiguous what "The $X directive must be followed by $Y" means, which becomes especially important when combined with godoc.

It doesn't appear to be well-documented that distinct comment blocks can exist between the compiler directive and $Y. (This comment and the one it cites are the only "documentation" I could find.)

How $X follows $Y is important for godoc where,

  1. if you want to exclude the Compiler Directive from the doc comment, you must split it off into a separate comment block, and
  2. if you want to attach documentation to the compiler directive but not have it appear in godoc, you must split it off into a separate comment block, and add your documentation there.

This proposal aims to relax the first rule above by allowing Compiler Directives to exist within a doc comment, and have it stripped by the godoc tool. The second rule seems reasonable and is unaffected by this proposal. (I've also rarely seen this rule used in practice, even within the Go source.)

This topic was previously discussed in #34276, but I wanted to reopen the discussion with the following, some of which is new:

  1. Having Compiler Directives "directly attached" to $Y is more natural, aids in readability and manual code refactoring, where it is otherwise very easy to miss the separate comment blocks above $Y when they need to be moved or deleted as a whole.

  2. When $Y is unexported, most examples I've seen attach Compiler Directives directly to it. While non-exported symbols don't appear in godoc, it generally makes their treatment very different to exported symbols, and then makes it easy to screw it up with exported symbols that do appear in godoc.

  3. I've seen lots of examples in the Go codebase (albeit in src/**/internal when using a godoc query string ?m=all) that get the above rules wrong:

    • In src/cmd/compile/internal/gc/go.go, the //go:generate for the Class enum type const block would appear in the godoc.
    • In src/cmd/compile/internal/ssa/value.go, the //go:noinline directive would appear on the AddArgX funcs godoc.
    • In src/cmd/internal/objabi/reloctype.go and src/cmd/internal/objabi/symkind.go similar //go:generate positioning errors exist.
    • (There are too many others to list here, but you get the point.)
  4. One of the arguments in doc: go:noinline directives in godoc #34276 for not having godoc strip Compiler Directives is that the author might want to include the directive in a comment. In all instances I've seen where that is the case, it typically looks like this:

    // The following is how we prevent a func from being inlined:
    //
    //   //go:noinline
    //   func example() {
    //   }
    

    That is, the Compiler Directive is typically a comment within a comment. I've sometimes seen the above written as a block comment too, though there is no ambiguity there as Compiler Directives are not allowed to be embedded in block comments (other than the special line comment which must be positioned at the very start).

  5. Parsing Go code via the AST is simpler when the Compiler Directive is directly attached to $Y: it exists in a node's associated *ast.CommentGroup. For detached comments, a parser needs to correlate with top-level comment groups, which is a bit more tricky, and especially when you want to mutate the AST using dave/dst.

Proposal

Have godoc strip Compiler Directives present in a doc comment associated with an exported symbol when,

  • one or more directives appear in the final lines of the doc comment with a preceding "blank comment" line, or
  • one or more directives appear as the only lines within the doc comment.

By this proposal, godoc would strip away all of the Compiler Directives below:

package example

// FourtyTwo always returns 42.
//
//go:noinline
//export FourtyTwo
func FourtyTwo() int {
  return 42
}

// DayOfWeek is an enum for days of the week.
type DayOfWeek int

//go:generate stringer -type DayOfWeek
const (
  DayOfWeekSun DayOfWeek = iota
  DayOfWeekMon
  DayOfWeekTue
  ...
)
@zephyrtronium
Copy link
Contributor

Is this not #37974? It seems like this has been implemented since Go 1.15:

go/src/go/ast/ast.go

Lines 125 to 128 in 3e48c03

if isDirective(c) {
// Ignore //go:noinline, //line, and so on.
continue
}

@jpap
Copy link
Contributor Author

jpap commented Jul 22, 2021

My apologies, it turns out my godoc binary was an older version. On update, everything works as you describe.

I'm also pleased to see that custom directives, like //my:directive also get stripped out! (That would've been my next request. 😃)

@jpap jpap closed this as completed Jul 22, 2021
@golang golang locked and limited conversation to collaborators Jul 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants