Commit a228e733 authored by Jeremiah Harmsen's avatar Jeremiah Harmsen Committed by Andrew Gerrand

go/doc/example: Fix bug causing false negatives for Example playability.

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
parent b13eac88
......@@ -166,6 +166,13 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
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
......
......@@ -18,6 +18,7 @@ const exampleTestFile = `
package foo_test
import (
"flag"
"fmt"
"log"
"os/exec"
......@@ -35,6 +36,38 @@ func ExampleImport() {
}
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 {
......@@ -49,6 +82,20 @@ 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
......@@ -78,6 +125,39 @@ func 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)
......
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