Go parser not detecting Doc comments on struct type

Issue

I am trying to read the assocated Doc comments on a struct type using Go’s parser and ast packages. In this example, the code simply uses itself as the source.

package main

import (
    "fmt"
    "go/ast"
    "go/parser"
    "go/token"
)

// FirstType docs
type FirstType struct {
    // FirstMember docs
    FirstMember string
}

// SecondType docs
type SecondType struct {
    // SecondMember docs
    SecondMember string
}

// Main docs
func main() {
    fset := token.NewFileSet() // positions are relative to fset

    d, err := parser.ParseDir(fset, "./", nil, parser.ParseComments)
    if err != nil {
        fmt.Println(err)
        return
    }

    for _, f := range d {
        ast.Inspect(f, func(n ast.Node) bool {
            switch x := n.(type) {
            case *ast.FuncDecl:
                fmt.Printf("%s:\tFuncDecl %s\t%s\n", fset.Position(n.Pos()), x.Name, x.Doc)
            case *ast.TypeSpec:
                fmt.Printf("%s:\tTypeSpec %s\t%s\n", fset.Position(n.Pos()), x.Name, x.Doc)
            case *ast.Field:
                fmt.Printf("%s:\tField %s\t%s\n", fset.Position(n.Pos()), x.Names, x.Doc)
            }

            return true
        })
    }
}

The comment docs for the func and fields are output no problem, but for some reason the ‘FirstType docs’ and ‘SecondType docs’ are nowhere to be found. What am I missing? Go version is 1.1.2.

(To run the above, save it into a main.go file, and go run main.go)

Solution

You need to use the go/doc package to extract documentation from the ast:

package main

import (
    "fmt"
    "go/doc"
    "go/parser"
    "go/token"
)

// FirstType docs
type FirstType struct {
    // FirstMember docs
    FirstMember string
}

// SecondType docs
type SecondType struct {
    // SecondMember docs
    SecondMember string
}

// Main docs
func main() {
    fset := token.NewFileSet() // positions are relative to fset

    d, err := parser.ParseDir(fset, "./", nil, parser.ParseComments)
    if err != nil {
        fmt.Println(err)
        return
    }

    for k, f := range d {
        fmt.Println("package", k)
        p := doc.New(f, "./", 0)

        for _, t := range p.Types {
            fmt.Println("  type", t.Name)
            fmt.Println("    docs:", t.Doc)
        }
    }
}

Answered By – mjibson

Answer Checked By – Cary Denson (GoLangFix Admin)

Leave a Reply

Your email address will not be published.