]> Cypherpunks repositories - gostls13.git/commitdiff
go/doc/example: Fix bug causing false negatives for Example playability.
authorJeremiah Harmsen <jeremiah@google.com>
Mon, 6 May 2013 17:15:16 +0000 (10:15 -0700)
committerAndrew Gerrand <adg@golang.org>
Mon, 6 May 2013 17:15:16 +0000 (10:15 -0700)
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

src/pkg/go/doc/example.go
src/pkg/go/doc/example_test.go

index 693ad5b9487ecc3e249d5411c9177af036514b40..2761083c7eed99c6828bfc19b4ee74808183b8da 100644 (file)
@@ -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
index b70efd93d4319aa72248328ec4b8b16318670b7f..e0477e3f6930b81d529e770b1304ae3b1391de5d 100644 (file)
@@ -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)