-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
x/tools/cmd/godoc: use go/types, show embedded methods #6127
Comments
Took a look at this. There are various scenarios to be considered.
So in a case like this - import "sync"
type T4 struct{}
// T4.M should appear as method of T5 only if AllMethods is set.
func (*T4) M() {}
type T5 struct {
T4
sync.Mutex
} when The relevant code is in @griesemer - I am not very well-versed with the |
@agnivade See https://github.com/golang/example/tree/master/gotypes . It's not hard to get to the methods, but the question is whether we want to run go/types every time somebody looks up some documentation. Or when we start the godoc server. Also, what happens when not all source code is available, etc. Running go/types all the time may work just fine for small repos. But for large repos, there will be issues of memory consumption (if we keep it all in memory), runtime (if we always type-check everything), caching (if we want to keep things running fast), consistency and correctness (if we have caches), etc., to name a few things that come to mind. I think making this work well requires a concentrated effort that goes beyond a "bug fix". This requires some design. |
Thanks! I will spend some time on it and update this thread. |
@griesemer - Sorry to bother you, but kinda got stuck here. I am trying to get the methods using The comment for
But I don't see the behavior to be consistent. Most possibly, I am doing something wrong. Would appreciate if you can take a look - // files is map[string]*ast.File from corpus.parseFiles
conf := types.Config{Importer: importer.Default()}
var ff []*ast.File
for _, de := range files {
ff = append(ff, de)
}
tpkg, err := conf.Check("something", fset, ff, nil)
if err != nil {
log.Fatal(err)
}
// Print the method sets of D
dType := tpkg.Scope().Lookup("D").Type()
mset := types.NewMethodSet(dType)
for i := 0; i < mset.Len(); i++ {
sel := mset.At(i)
log.Printf("%#v\n", sel.Obj()) // -- just shows C
}
obj, _, _ := types.LookupFieldOrMethod(dType, true, tpkg, "Lock") // -- gives proper info
log.Printf("%#v\n", obj) source - type a struct {
B string
}
func (a) C() {}
type D struct {
a
sync.Mutex
} Thank you for your time. |
@agnivade The method set of In your code, you need to provide the type dType := types.NewPointer(tpkg.Scope().Lookup("D").Type()) Here's a complete stand-alone program that prints all the desired methods: package main
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
)
const src = `
package p
import "sync"
type a struct {
B string
}
func (a) C() {}
type D struct {
a
sync.Mutex
}
`
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "p.go", src, 0)
if err != nil {
log.Fatal(err)
}
files := []*ast.File{f}
conf := types.Config{Importer: importer.Default()}
pkg, err := conf.Check("p", fset, files, nil)
if err != nil {
log.Fatal(err)
}
typ := types.NewPointer(pkg.Scope().Lookup("D").Type())
mset := types.NewMethodSet(typ)
for i := 0; i < mset.Len(); i++ {
log.Printf("%d: %v\n", i, mset.At(i))
}
} Output:
|
PS: You may also want to look at |
Awesome, thank you ! I will look into it and prepare a prototype for 1.12. |
@griesemer - It looks like getting the documentation for the method is slightly difficult. To maintain consistency with the other methods, we need to show the doc for embedded methods too. The Is there anything simple that can be done here ? |
ping @griesemer |
@agnivade go/types doesn't know anything about comments - there's no way to get the documentation for a method from go/types alone. You'll need to cross-reference the go/ast file with go/types (basically, find the objects for each method and then use the method matching the desired object). go/types doesn't point back to the AST so as to not hold on to a large data structure inadvertently. |
But the go/ast file won't contain the methods of the required import package right ? I mean if my file is something like this - package p
import "sync"
type a struct {
B string
}
func (a) C() {}
type D struct {
a
sync.Mutex
} Then the ast will have access to methods of |
@agnivade Correct. An ast.File contains literally what's in the source - no more and no less. You'd have to actually get the ast.File(s) for the imported package. It's expensive. |
for anyone confused by this page, the above discussion is NOT what happens currently. For example this type: https://godocs.io/bufio#ReadWriter embeds this type: https://godocs.io/bufio#Reader which includes this method: https://godocs.io/bufio#Reader.Buffered but the wrapper type documents NO methods. |
@4cq2 you can try Golds instead: https://docs.go101.org/std/pkg/bufio.html#name-ReadWriter |
btw. although |
@go101 no thank you. I actually prefer the embedded methods NOT be documented. as is done with https://godocs.io and https://pkg.go.dev. if I want to browse the embedded methods, I will visit the embedded types. also your linked documentation is quite confusing, as it makes no distinction between an embedded method and a normal method, when those two items are quite different. |
For general using, there is almost no distinction. Now you can click a listed method to see which type this method is declared on. Thanks for your suggestions, I will add a todo item to support an option to show full paths of methods (just like the current implementation for showing the paths of embedding fields). |
The text was updated successfully, but these errors were encountered: