Commit 3191a235 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder Committed by Robert Griesemer

go/doc: propagate types from unexported constants

When constants were declared using unexported constants,
the type information was lost when those constants were filtered out.
This CL propagates the type information of unexported constants
so that it is available for display.

This is a follow-up to CL 144110044, which fixed this problem
specifically for _ constants.

Updates #5397.

Change-Id: I3f0c767a4007d88169a5634ab2870deea4e6a740
Reviewed-on: https://go-review.googlesource.com/2091Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 43178697
......@@ -26,6 +26,17 @@ func filterIdentList(list []*ast.Ident, blankOk bool) []*ast.Ident {
return list[0:j]
}
// hasExportedOrBlankName reports whether list contains any exported or blank names.
//
func hasExportedOrBlankName(list []*ast.Ident) bool {
for _, x := range list {
if x.IsExported() || x.Name == "_" {
return true
}
}
return false
}
// removeErrorField removes anonymous fields named "error" from an interface.
// This is called when "error" has been determined to be a local name,
// not the predeclared type.
......@@ -165,7 +176,47 @@ func (r *reader) filterSpec(spec ast.Spec, tok token.Token) bool {
return false
}
// copyConstType returns a copy of typ with position pos.
// typ must be a valid constant type.
// In practice, only (possibly qualified) identifiers are possible.
//
func copyConstType(typ ast.Expr, pos token.Pos) ast.Expr {
switch typ := typ.(type) {
case *ast.Ident:
return &ast.Ident{Name: typ.Name, NamePos: pos}
case *ast.SelectorExpr:
if id, ok := typ.X.(*ast.Ident); ok {
// presumably a qualified identifier
return &ast.SelectorExpr{
Sel: ast.NewIdent(typ.Sel.Name),
X: &ast.Ident{Name: id.Name, NamePos: pos},
}
}
}
return nil // shouldn't happen, but be conservative and don't panic
}
func (r *reader) filterSpecList(list []ast.Spec, tok token.Token) []ast.Spec {
if tok == token.CONST {
// Propagate any type information that would get lost otherwise
// when unexported constants are filtered.
var prevType ast.Expr
for _, spec := range list {
spec := spec.(*ast.ValueSpec)
if spec.Type == nil && prevType != nil {
// provide current spec with an explicit type
spec.Type = copyConstType(prevType, spec.Pos())
}
if hasExportedOrBlankName(spec.Names) {
// both exported and blank names are preserved
// so there's no need to propagate the type
prevType = nil
} else {
prevType = spec.Type
}
}
}
j := 0
for _, s := range list {
if r.filterSpec(s, tok) {
......
......@@ -4,10 +4,30 @@ PACKAGE blank
IMPORTPATH
testdata/blank
IMPORTS
os
FILENAMES
testdata/blank.go
CONSTANTS
// T constants counting from unexported constants.
const (
C1 T
C2
C3
C4 int
)
// Constants with an imported type that needs to be propagated.
const (
Default os.FileMode = 0644
Useless = 0312
WideOpen = 0777
)
// Package constants.
const (
_ int = iota
......@@ -28,7 +48,7 @@ TYPES
//
type T int
// T constants.
// T constants counting from a blank constant.
const (
_ T = iota
T1
......
......@@ -4,10 +4,25 @@ PACKAGE blank
IMPORTPATH
testdata/blank
IMPORTS
os
FILENAMES
testdata/blank.go
CONSTANTS
// T constants counting from unexported constants.
const (
tweedledee T = iota
tweedledum
C1
C2
alice
C3
redQueen int = iota
C4
)
// Package constants.
const (
_ int = iota
......@@ -15,6 +30,14 @@ CONSTANTS
I2
)
// Constants with an imported type that needs to be propagated.
const (
zero os.FileMode = 0
Default = 0644
Useless = 0312
WideOpen = 0777
)
VARIABLES
//
......@@ -37,7 +60,7 @@ TYPES
//
type T int
// T constants.
// T constants counting from a blank constant.
const (
_ T = iota
T1
......
......@@ -4,10 +4,30 @@ PACKAGE blank
IMPORTPATH
testdata/blank
IMPORTS
os
FILENAMES
testdata/blank.go
CONSTANTS
// T constants counting from unexported constants.
const (
C1 T
C2
C3
C4 int
)
// Constants with an imported type that needs to be propagated.
const (
Default os.FileMode = 0644
Useless = 0312
WideOpen = 0777
)
// Package constants.
const (
_ int = iota
......@@ -28,7 +48,7 @@ TYPES
//
type T int
// T constants.
// T constants counting from a blank constant.
const (
_ T = iota
T1
......
......@@ -6,15 +6,37 @@
// See issue 5397.
package blank
import "os"
type T int
// T constants.
// T constants counting from a blank constant.
const (
_ T = iota
T1
T2
)
// T constants counting from unexported constants.
const (
tweedledee T = iota
tweedledum
C1
C2
alice
C3
redQueen int = iota
C4
)
// Constants with an imported type that needs to be propagated.
const (
zero os.FileMode = 0
Default = 0644
Useless = 0312
WideOpen = 0777
)
// Package constants.
const (
_ int = iota
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment