aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremiah Harmsen <jeremiah@google.com>2013-05-06 10:15:16 -0700
committerAndrew Gerrand <adg@golang.org>2013-05-06 10:15:16 -0700
commita228e733b9908c3839cbca9c3545de0a3f1aba47 (patch)
treefa14810bb07c9f46f0486daae985ca8450d1dd8b
parentb13eac88aca4ac27174e3f32284637d8d8d0915d (diff)
downloadgo-a228e733b9908c3839cbca9c3545de0a3f1aba47.tar.gz
go-a228e733b9908c3839cbca9c3545de0a3f1aba47.zip
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
-rw-r--r--src/pkg/go/doc/example.go7
-rw-r--r--src/pkg/go/doc/example_test.go80
2 files changed, 87 insertions, 0 deletions
diff --git a/src/pkg/go/doc/example.go b/src/pkg/go/doc/example.go
index 693ad5b948..2761083c7e 100644
--- a/src/pkg/go/doc/example.go
+++ b/src/pkg/go/doc/example.go
@@ -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
diff --git a/src/pkg/go/doc/example_test.go b/src/pkg/go/doc/example_test.go
index b70efd93d4..e0477e3f69 100644
--- a/src/pkg/go/doc/example_test.go
+++ b/src/pkg/go/doc/example_test.go
@@ -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)