From: Jeremiah Harmsen Date: Mon, 6 May 2013 17:15:16 +0000 (-0700) Subject: go/doc/example: Fix bug causing false negatives for Example playability. X-Git-Tag: go1.1rc2~7 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a228e733b9908c3839cbca9c3545de0a3f1aba47;p=gostls13.git 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 --- 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: "", + }, } 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)