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: show exported fields promoted from unexported anonymous fields #6600

Open
ugorji opened this Issue Oct 16, 2013 · 14 comments

Comments

Projects
None yet
9 participants
@ugorji
Contributor

ugorji commented Oct 16, 2013

Within my code, I have the following structure.

type common struct {
    Option1 bool
}

func (c *common) Method1() {
}

type A struct {
    OptionA int
    common
}

type B struct {
    OptionB int
    common
}

I want godoc to show that type A and type B have field Option1 available, and Method1 in
their method sets.

However, godoc would not show Option1, because common is not exported. It however show
Method1 (the full method set).

The only current workaround is to export common (which really is an internal
implementation detail), or duplicate the functionality across all types that share it. 

TO fix, godoc should show these promoted fields got from unexported anonymous fields. 

For example, godoc output for A could look like:

type A struct {
    OptionA int
    // contains filtered or unexported fields
    // Available from unexported anonymous fields
    Option1 bool
}


Which version are you using?  (run 'go version')
go version devel +47b2b07a837f Fri Oct 11 16:39:40 2013 -0700 linux/amd64

Please provide any additional information below.
@rsc

This comment has been minimized.

Contributor

rsc commented Oct 18, 2013

Comment 1:

Labels changed: added priority-later, removed priority-triage.

Status changed to Accepted.

@rsc

This comment has been minimized.

Contributor

rsc commented Nov 27, 2013

Comment 2:

Labels changed: added go1.3maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Dec 4, 2013

Comment 3:

Labels changed: added release-none, removed go1.3maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Dec 4, 2013

Comment 4:

Labels changed: added repo-tools.

@ugorji ugorji added accepted labels Dec 4, 2013

@rsc rsc added this to the Unplanned milestone Apr 10, 2015

@rsc rsc changed the title from cmd/godoc: show exported fields promoted from unexported anonymous fields to x/tools/cmd/godoc: show exported fields promoted from unexported anonymous fields Apr 14, 2015

@rsc rsc removed the repo-tools label Apr 14, 2015

@alecthegeek

This comment has been minimized.

alecthegeek commented Jul 27, 2017

I have what I think is the same problem. Public receiver methods (on a hidden type) do not have their document strings displayed. Consider this code

//Package showme demonstrates that public receivers on a hidden type are not documented
package showme

type hiddenType struct {
  i int
  s string
}
type PublicType struct {
  i int
  s string
}

// PublicFA should be documented
func (hiddenType) PublicFA(){
  //do something boring
}

// PublicFB will be documented
func (PublicType) PublicFB(){
  //do something boring
}

Method PublicFA is not documented when I run godoc.

@agnivade

This comment has been minimized.

Member

agnivade commented May 4, 2018

@alecthegeek - Your issue is different. PublicFA should not be documented because it is attached to hiddenType which is not exported. You need to expose hiddenType if you want PublicFA to be visible.

This issue is about displaying exported fields from embedded fields in a type which itself is exported.

@agnivade

This comment has been minimized.

Member

agnivade commented May 4, 2018

Interesting thing to note is if common is exported, Method1() stops showing up. Probably related to #6127.

@agnivade agnivade self-assigned this Aug 23, 2018

@gopherbot

This comment has been minimized.

gopherbot commented Aug 24, 2018

Change https://golang.org/cl/131176 mentions this issue: go/doc: show exported fields of embedded structs

@griesemer

This comment has been minimized.

Contributor

griesemer commented Sep 10, 2018

Before we write any more code for this, we need to decide if and what we should do about this.

@agnivade

This comment has been minimized.

Member

agnivade commented Sep 11, 2018

Copying over @dsnet's thoughts from the CL for completeness -

I don't think we should do this. I have following concerns:

  • Uplifting exported fields from embedded unexported structs to the parent struct lies to the user about the true nature of the type. Now godoc claims that the parent has a field of some given name, but instantiating the struct as a literal does not match what godoc says. For example (from your testdata), U1 claims to have a field F1, so I would expect to be able to write a literal of the form U1{F1: "string"}, but this is not valid and my code fails to build.
  • Sometimes people deliberately embed an unexported type precisely because they want to hide the exported fields.
  • This bakes in more understanding of type information into godoc that fundamentally belongs in go/types. When do we stop giving more understanding of types to godoc?
@go101

This comment has been minimized.

go101 commented Sep 11, 2018

I'm some surprised that the following cmd doesn't work:

$ go doc *sync.Cond
doc: invalid identifier "*sync"
exit status 1
@dsnet

This comment has been minimized.

Member

dsnet commented Sep 20, 2018

@go101, what you're describing is orthogonal to this issue. The go doc tool does not know about pointers. Instead, you should do:

$ go doc sync.Cond
type Cond struct {

	// L is held while observing or changing the condition
	L Locker

	// Has unexported fields.
}
    Cond implements a condition variable, a rendezvous point for goroutines
    waiting for or announcing the occurrence of an event.

    Each Cond has an associated Locker L (often a *Mutex or *RWMutex), which
    must be held when changing the condition and when calling the Wait method.

    A Cond must not be copied after first use.


func NewCond(l Locker) *Cond
func (c *Cond) Broadcast()
func (c *Cond) Signal()
@go101

This comment has been minimized.

go101 commented Nov 9, 2018

There are more cases of exported methods/fields are not listed by doc cmd and godoc webpages.

  1. the methods and fields of exported variables of unexported types.
  2. the methods and fields of the exported alias of unexported types
@ddrake17

This comment has been minimized.

ddrake17 commented Dec 5, 2018

+1 for allowing documentation of embedded struct's exported fields. In response to @dsnet and @agnivade said:

  • It's true that there are some differences and so perhaps the fields should not be given the exact same doc status as regular exported fields, but I think there is still value in showing the fields since users can access them. The example in the issue report shows one way of documenting them differently.
  • One issue pointed out was forming a struct literal but a clear differentiation in comment would show the user they can't create it the normal way.
  • Also you can still access the embedded fields in other ways that are exactly the same as if they were fields of the exported struct itself (e.g. using the example code in the issue report, if B.Option == false ). Although you can access these fields and use them there isn't a good way to tell this from reading the docs since they aren't shown at all.
  • If package writers don't want people accessing exported fields then there are multiple ways to hide them like unexporting them, or embedding the struct with a named unexported field.

I think the proposed doc solution in the report was good and would differentiate things enough so users were not confused

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment