2

I'm currently working on documentation generator that will parse Go code to produce a custom documentation. I need to access to the comments written inside a function. But I can't retrieve these comments in the AST, neither with the go/doc. Here is an example :

package main

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

// GetFoo comments I can find easely
func GetFoo() {
    // Comment I would like to access
    test := 1
    fmt.Println(test)
}

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, "./", 2)

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

        for _, v := range p.Vars {
            fmt.Println("type", v.Names)
            fmt.Println("docs:", v.Doc)
        }

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

        for _, n := range p.Notes {
            fmt.Println("body", n[0].Body)
        }
    }
}

It's easy to find GetFoo comments I can find easely but not Comment I would like to access I have seen this post quite similar question Go parser not detecting Doc comments on struct type but for exported types

Is there any way to do that ? Thank you !

al3x
  • 1,756
  • 2
  • 13
  • 10
  • You should find that comment on the first node of the function body (the initializer for `test`). – Peter Oct 05 '17 at 14:53
  • if I iterate over the body of the func `x.Body.List` I find nothing, maybe I don't search at the right place ? – al3x Oct 05 '17 at 15:52
  • 1
    You may want to check out ast package and the example https://golang.org/pkg/go/ast/#example_CommentMap – Ravi R Oct 10 '17 at 11:21
  • @Ravi it seems that the CommentMap is the easiest way to do what I want. Thank you !! – al3x Oct 11 '17 at 07:07

1 Answers1

3

The problem is that the doc.New functionality is only parsing for documentation strings, and the comment inside the function is not part of the "documentation".

You'll want to directly iterate the ast of the files in the package.

package main

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

// GetFoo comments I can find easely
func GetFoo() {
        // Comment I would like to access
        test := 1
        fmt.Println(test)
}

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)
                for n, f := range f.Files {
                        fmt.Printf("File name: %q\n", n)
                        for i, c := range f.Comments {
                                fmt.Printf("Comment Group %d\n", i)
                                for i2, c1 := range c.List {
                                        fmt.Printf("Comment %d: Position: %d, Text: %q\n", i2, c1.Slash, c1.Text)
                                }
                        }
                }

        }
}
John Weldon
  • 39,849
  • 11
  • 94
  • 127
  • thank you, I just need to understand how I can spot that this comment is within a function – al3x Oct 05 '17 at 16:04
  • 1
    @al3x use `FuncDecl`'s `Pos` and `End` to determine the body start and end, then loop over the `*ast.Package.Files[].Comments[].List[]` fields to loop over all comments in the package, each comment has a `Slash` position, if it's > start and < end then you've got your comment. – mkopriva Oct 05 '17 at 16:07