Allows Examples with KeyValue expressions to be playable in godoc.
During the traversal of the abstract syntax tree any KeyValueExpr Key.Name was incorrectly being added as an unresolved identifier.
Since this identifier could not be provided the Example was marked as unplayable.
This updates the AST traversal to skip Keys (but continue traversing the Values).
Example of problematic AST now fixed (see L99 where "UpperBound" was being added as a missing identifier):
81 . . . . . . . . . Values: []ast.Expr (len = 1) {
82 . . . . . . . . . . 0: *ast.UnaryExpr {
83 . . . . . . . . . . . OpPos: 12:19
84 . . . . . . . . . . . Op: &
85 . . . . . . . . . . . X: *ast.CompositeLit {
86 . . . . . . . . . . . . Type: *ast.SelectorExpr {
87 . . . . . . . . . . . . . X: *ast.Ident {
88 . . . . . . . . . . . . . . NamePos: 12:20
89 . . . . . . . . . . . . . . Name: "t_proto"
90 . . . . . . . . . . . . . }
91 . . . . . . . . . . . . . Sel: *ast.Ident {
92 . . . . . . . . . . . . . . NamePos: 12:41
93 . . . . . . . . . . . . . . Name: "BConfig"
94 . . . . . . . . . . . . . }
95 . . . . . . . . . . . . }
96 . . . . . . . . . . . . Lbrace: 12:79
97 . . . . . . . . . . . . Elts: []ast.Expr (len = 2) {
98 . . . . . . . . . . . . . 0: *ast.KeyValueExpr {
99 . . . . . . . . . . . . . . Key: *ast.Ident {
100 . . . . . . . . . . . . . . . NamePos: 13:3
101 . . . . . . . . . . . . . . . Name: "UpperBound"
102 . . . . . . . . . . . . . . }
103 . . . . . . . . . . . . . . Colon: 13:13
104 . . . . . . . . . . . . . . Value: *ast.CallExpr {
105 . . . . . . . . . . . . . . . Fun: *ast.SelectorExpr {
106 . . . . . . . . . . . . . . . . X: *ast.Ident {
107 . . . . . . . . . . . . . . . . . NamePos: 13:15
108 . . . . . . . . . . . . . . . . . Name: "proto"
109 . . . . . . . . . . . . . . . . }
110 . . . . . . . . . . . . . . . . Sel: *ast.Ident {
111 . . . . . . . . . . . . . . . . . NamePos: 13:21
112 . . . . . . . . . . . . . . . . . Name: "Float32"
113 . . . . . . . . . . . . . . . . }
R=adg
CC=gobot, golang-dev, gri
https://golang.org/cl/
8569045
ast.Inspect(e.X, inspectFunc)
return false
}
+ // For key value expressions, only inspect the value
+ // as the key should be resolved by the type of the
+ // composite literal.
+ if e, ok := n.(*ast.KeyValueExpr); ok {
+ ast.Inspect(e.Value, inspectFunc)
+ return false
+ }
if id, ok := n.(*ast.Ident); ok {
if id.Obj == nil {
unresolved[id.Name] = true
package foo_test
import (
+ "flag"
"fmt"
"log"
"os/exec"
}
fmt.Printf("The date is %s\n", out)
}
+
+func ExampleKeyValue() {
+ v := struct {
+ a string
+ b int
+ }{
+ a: "A",
+ b: 1,
+ }
+ fmt.Print(v)
+ // Output: a: "A", b: 1
+}
+
+func ExampleKeyValueImport() {
+ f := flag.Flag{
+ Name: "play",
+ }
+ fmt.Print(f)
+ // Output: Name: "play"
+}
+
+var keyValueTopDecl = struct {
+ a string
+ b int
+}{
+ a: "B",
+ b: 2,
+}
+
+func ExampleKeyValueTopDecl() {
+ fmt.Print(keyValueTopDecl)
+}
`
var exampleTestCases = []struct {
Name: "Import",
Play: exampleImportPlay,
},
+ {
+ Name: "KeyValue",
+ Play: exampleKeyValuePlay,
+ Output: "a: \"A\", b: 1\n",
+ },
+ {
+ Name: "KeyValueImport",
+ Play: exampleKeyValueImportPlay,
+ Output: "Name: \"play\"\n",
+ },
+ {
+ Name: "KeyValueTopDecl",
+ Play: "<nil>",
+ },
}
const exampleHelloPlay = `package main
}
`
+const exampleKeyValuePlay = `package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ v := struct {
+ a string
+ b int
+ }{
+ a: "A",
+ b: 1,
+ }
+ fmt.Print(v)
+}
+`
+
+const exampleKeyValueImportPlay = `package main
+
+import (
+ "flag"
+ "fmt"
+)
+
+func main() {
+ f := flag.Flag{
+ Name: "play",
+ }
+ fmt.Print(f)
+}
+`
+
func TestExamples(t *testing.T) {
fs := token.NewFileSet()
file, err := parser.ParseFile(fs, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)