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

cmd/doc: should print package imports used in external argument and return types #22069

Closed
willfaught opened this issue Sep 27, 2017 · 13 comments
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.

Comments

@willfaught
Copy link
Contributor

So you can see which import paths the qualifiers map to. Without this info, documentation sources like godoc.org are more useful than go doc in these situations.

What did you do?

$ go doc google.golang.org/grpc SendHeader

What did you expect to see?

Something like:

import (
    context "context"
    metadata "google.golang.org/grpc/metadata"
)

func SendHeader(ctx context.Context, md metadata.MD) error
    SendHeader sends header metadata. It may be called at most once. The
    provided md and headers set by SetHeader() will be sent.

...so you can tell what the metadata in md metadata.MD (or even context) is. Maybe you can get fancy and omit the explicit import alias if the package name matches the import path's base name. It's just a rough sketch of the idea.

What did you see instead?

func SendHeader(ctx context.Context, md metadata.MD) error
    SendHeader sends header metadata. It may be called at most once. The
    provided md and headers set by SetHeader() will be sent.

What's metadata? No idea, given just this info. The full package doc doesn't have the info either.

System details

go version go1.9 darwin/amd64
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/willfaught/Developer/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.9/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.9/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_1/ggvd2t1x7hz_185crsb36zlr0000gp/T/go-build557654974=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOROOT/bin/go version: go version go1.9 darwin/amd64
GOROOT/bin/go tool compile -V: compile version go1.9
uname -v: Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64
ProductName:	Mac OS X
ProductVersion:	10.12.6
BuildVersion:	16G29
lldb --version: lldb-900.0.45
  Swift-4.0
@dsnet dsnet changed the title doc: should document package imports used in exports cmd/doc: should print package imports used in external argument and return types Sep 28, 2017
@dsnet
Copy link
Member

dsnet commented Sep 28, 2017

\cc @robpike to decide whether to add this feature.

@dsnet dsnet added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Sep 28, 2017
@dsnet
Copy link
Member

dsnet commented Sep 28, 2017

Two possible options:

  • Print the packages for external types when listing a specific function. But this can be noisy for common packages like io and I'm not a fan of special casing "common" packages like context and io.
  • Only print the imported packages that are exposed to the external API when you do the full listing with go doc. I like this approach better. Although, you will need to deal with package renames and conflicts.

@robpike
Copy link
Contributor

robpike commented Sep 28, 2017

This could make the output a lot messier, which would be counter to the idea behind the command, which is a quick and easy way to answer simple API questions.

I never think about this problem anyway. Goimports takes care of it for me.

I'll let others make comments. The idea of doing this only for "go doc " isn't right, as it sums all the imports any function/method uses, but any individual one may use none of them.

@willfaught
Copy link
Contributor Author

I like the option of printing it with the package only. It keeps the individual declaration doc small.

which is a quick and easy way to answer simple API questions

Isn't "which type/package is this?" a simple API question?

I never think about this problem anyway. Goimports takes care of it for me.

Doesn't goimports only work in that case if you've already go-gotten the package and there's no other "closer" matching package that goimports could resolve the name to?

In any case, this assumes the situation is that you're in an editor trying to call a function, whereas go doc is a command-line tool that can be used solely in the terminal to explore APIs.

The idea of doing this only for "go doc " isn't right

I think this would add feature parity with godoc.org, which links package qualifiers to their documentation automatically. You can get information from godoc.org that you can't get with go doc. It'd be nice if go doc was as capable as godoc.org so you don't need a network connection to read and explore documentation.

as it sums all the imports any function/method uses, but any individual one may use none of them.

I'm not sure I follow. In my example above, the only imports shown for the func are the ones that it exposes, not all the imports exposed by the entire package.

@robpike
Copy link
Contributor

robpike commented Sep 28, 2017

Go doc tells you which package it is. It doesn't at the moment tell you all the packages you must import for dependencies, though. That's the question at hand.

To your last point, I was referring to @dsnet's point about "full listings", that is, typing

go doc

with no arguments.

@willfaught
Copy link
Contributor Author

Go doc tells you which package it is.

(I can't tell which point this replies to. Can you please clarify?) Which package do you mean? If you mean the package containing the thing you're reading the documentation for, then sure, because you told it the package, but that's not the issue. If you mean the package of the imported type exposed by the thing you're reading the documentation for, then I don't think it does, as my example above showed:

$ go doc google.golang.org/grpc SendHeader
func SendHeader(ctx context.Context, md metadata.MD) error
    SendHeader sends header metadata. It may be called at most once. The
    provided md and headers set by SetHeader() will be sent.

$ go doc ???/metadata MD # What is metadata?

To your last point, I was referring to @dsnet's point about "full listings"

It seems to me that exposed imports are a part of a package's exported interface, so understanding them is necessary to understanding the interface, so they should be part of the package's documentation. They are already part of the package's documentation for godoc.org in the form of hyperlinks, but they can't be represented as hyperlinks in the terminal, so go doc should print out the info explicitly in some way. Godoc.org already "sums all the imports any function/method uses" in the form of those package hyperlinks.

@willfaught
Copy link
Contributor Author

Another option could be showing the import blocks as collapsed with a "...", like const/var blocks are:

const Invalid BasicKind = iota ...
var Universe *Scope ...

For example, the import metadata "google.golang.org/grpc/metadata" ... in:

$ go doc google.golang.org/grpc
package grpc // import "google.golang.org/grpc"

Package grpc implements an RPC system called gRPC.

See grpc.io for more information about gRPC.

import metadata "google.golang.org/grpc/metadata" ...
[...]
func SendHeader(ctx context.Context, md metadata.MD) error
[...]

So you'd do a go doc google.golang.org/grpc metadata to expand the block and see the rest of the imports, like for consts/vars:

$ go doc google.golang.org/grpc metadata
import (
    metadata "google.golang.org/grpc/metadata"
    [...]
)

$

@willfaught
Copy link
Contributor Author

willfaught commented Oct 18, 2017

It occurred to me that it's possible for the same package alias to refer to different packages across multiple files. If you only showed the imports at the package scope, there might not be one alias you could pick for an imported package that would work for the whole package. Basically, godoc.org is presenting the imports per file/declaration as URLs. So the equivalent in the terminal would be printing that import info with each declaration:

import (
    "context"
    "google.golang.org/grpc/metadata"
)

func SendHeader(ctx context.Context, md metadata.MD) error
    SendHeader sends header metadata. It may be called at most once. The
    provided md and headers set by SetHeader() will be sent.

The alternative is to normalize the aliases in the tool so they work across all the package declarations, but then the doc might not match the source, and you'd have to figure out how to always pick a good alias.

@rsc
Copy link
Contributor

rsc commented Oct 23, 2017

@willfaught, does 'go doc metadata.MD' fail for you? It should find the right package.

There's a tension in 'go doc' between having short concise output and being completely precise. For links and such it seems like the godoc web server would be a better starting point anyway.

Provided 'go doc metadata.MD' works I think we should leave this alone.

@willfaught
Copy link
Contributor Author

does 'go doc metadata.MD' fail for you? It should find the right package. [...] Provided 'go doc metadata.MD' works I think we should leave this alone.

It depends:

$ cd ~
$ go doc metadata.MD               
package metadata // import "google.golang.org/grpc/metadata"

type MD map[string][]string
    MD is a mapping from metadata keys to values. Users should use the following
    two convenience functions New and Pairs to generate MD.


func FromIncomingContext(ctx context.Context) (md MD, ok bool)
func FromOutgoingContext(ctx context.Context) (md MD, ok bool)
func Join(mds ...MD) MD
func New(m map[string]string) MD
func Pairs(kv ...string) MD
func (md MD) Copy() MD
func (md MD) Len() int

But:

$ cd ~
$ echo "package metadata\n\ntype MD int\n" > $GOPATH/src/github.com/willfaught/metadata/m.go
$ go doc metadata.MD
package metadata // import "github.com/willfaught/metadata"

type MD int

Also, strangely:

$ cd ~
$ echo "package metadata\n\ntype NOOOOOOOOTMD int\n" > $GOPATH/src/metadata/m.go
$ go doc metadata.MD
doc: no symbol MD in package metadata
exit status 1

(Apparently, if it's a "root" package, it matches only on package name and not also declaration name. Bug?)

There's a tension in 'go doc' between having short concise output and being completely precise.

Adding an import foo "bar" ... line to the package doc doesn't seem to impact the concision much, but for the other solutions, I agree.

Would adding a flag to show the import info be an option? There's a flag to show unexported declarations.

For links and such it seems like the godoc web server would be a better starting point anyway.

My point, though, is that go doc is a worse starting point, and that it should be equal.

FWIW, I like that go doc lets me read documentation without needing to consult separate content like JavaDoc. IMO, go doc is a great Go innovation for this reason. It seems a shame to go 95% of the distance and then stop. It's so close! :)

@rsc
Copy link
Contributor

rsc commented Oct 24, 2017

It's so close! :)

But if you add a line that's noise 99% of the time, then that makes it worse, not better. I could see making 'go doc grpc.metadata' work, perhaps. But nothing that changes the default output.

@willfaught
Copy link
Contributor Author

But if you add a line that's noise 99% of the time, then that makes it worse, not better.

Why would it be noise? In the simplest scenario, like for "strings", no imports are exposed, so there wouldn't be a line at all. If there are exposed imports, then you need all that info to fully understand the package's declarations. There's no useless info in those scenarios.

Do you mean noise in the sense that you might only be interested in declarations that don't expose imports? If so, how is that noisier than listing all constant blocks when all I want to see is the functions? go doc summarizes constant blocks with the first declaration and a "..." to minimize that noise, which is the same idea here for exposed imports. If it's done that way, I don't see how it would be noisier than those constant blocks.

I could see making 'go doc grpc.metadata' work, perhaps

If "grpc.metadata" were the name of a directory in $GOPATH/src, it would clash. I see what you mean, though. Maybe use the ... wildcard like ".../grpc/metadata"? But this assumes you know what the parent directory of the metadata package is. If you know that, then you probably already know which package metadata is.

@rsc
Copy link
Contributor

rsc commented Oct 30, 2017

I understand your point but I don't see a good way to add this to the command-line version. For complete info like this the suggested source is a godoc web server (either locally or at godoc.org).

@rsc rsc closed this as completed Oct 30, 2017
@golang golang locked and limited conversation to collaborators Oct 30, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

5 participants