From 60544b698ed1310dd3c5dbf67f73f29938d64e0d Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Mon, 7 Jan 2013 19:36:38 +1100 Subject: [PATCH] go/doc: recursively inspect selector expressions Also adds a couple of simple tests for doc.Examples. Fixes #4561. R=golang-dev, dave, rsc CC=golang-dev https://golang.org/cl/7067048 --- src/pkg/go/doc/example.go | 15 ++--- src/pkg/go/doc/example_test.go | 111 +++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 src/pkg/go/doc/example_test.go diff --git a/src/pkg/go/doc/example.go b/src/pkg/go/doc/example.go index d9e8c39a54..c7a0cf8c6d 100644 --- a/src/pkg/go/doc/example.go +++ b/src/pkg/go/doc/example.go @@ -148,13 +148,13 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { // Find unresolved identifiers and uses of top-level declarations. unresolved := make(map[string]bool) usesTopDecl := false - ast.Inspect(body, func(n ast.Node) bool { - // For an expression like fmt.Println, only add "fmt" to the - // set of unresolved names. + var inspectFunc func(ast.Node) bool + inspectFunc = func(n ast.Node) bool { + // For selector expressions, only inspect the left hand side. + // (For an expression like fmt.Println, only add "fmt" to the + // set of unresolved names, not "Println".) if e, ok := n.(*ast.SelectorExpr); ok { - if id, ok := e.X.(*ast.Ident); ok && id.Obj == nil { - unresolved[id.Name] = true - } + ast.Inspect(e.X, inspectFunc) return false } if id, ok := n.(*ast.Ident); ok { @@ -165,7 +165,8 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { } } return true - }) + } + ast.Inspect(body, inspectFunc) if usesTopDecl { // We don't support examples that are not self-contained (yet). return nil diff --git a/src/pkg/go/doc/example_test.go b/src/pkg/go/doc/example_test.go new file mode 100644 index 0000000000..b70efd93d4 --- /dev/null +++ b/src/pkg/go/doc/example_test.go @@ -0,0 +1,111 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package doc_test + +import ( + "bytes" + "go/doc" + "go/format" + "go/parser" + "go/token" + "strings" + "testing" +) + +const exampleTestFile = ` +package foo_test + +import ( + "fmt" + "log" + "os/exec" +) + +func ExampleHello() { + fmt.Println("Hello, world!") + // Output: Hello, world! +} + +func ExampleImport() { + out, err := exec.Command("date").Output() + if err != nil { + log.Fatal(err) + } + fmt.Printf("The date is %s\n", out) +} +` + +var exampleTestCases = []struct { + Name, Play, Output string +}{ + { + Name: "Hello", + Play: exampleHelloPlay, + Output: "Hello, world!\n", + }, + { + Name: "Import", + Play: exampleImportPlay, + }, +} + +const exampleHelloPlay = `package main + +import ( + "fmt" +) + +func main() { + fmt.Println("Hello, world!") +} +` +const exampleImportPlay = `package main + +import ( + "fmt" + "log" + "os/exec" +) + +func main() { + out, err := exec.Command("date").Output() + if err != nil { + log.Fatal(err) + } + fmt.Printf("The date is %s\n", out) +} +` + +func TestExamples(t *testing.T) { + fs := token.NewFileSet() + file, err := parser.ParseFile(fs, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments) + if err != nil { + t.Fatal(err) + } + for i, e := range doc.Examples(file) { + c := exampleTestCases[i] + if e.Name != c.Name { + t.Errorf("got Name == %q, want %q", e.Name, c.Name) + } + if w := c.Play; w != "" { + var g string // hah + if e.Play == nil { + g = "" + } else { + b := new(bytes.Buffer) + if err := format.Node(b, fs, e.Play); err != nil { + t.Fatal(err) + } + g = b.String() + } + if g != w { + t.Errorf("%s: got Play == %q, want %q", c.Name, g, w) + } + } + if g, w := e.Output, c.Output; g != w { + t.Errorf("%s: got Output == %q, want %q", c.Name, g, w) + } + } +} -- 2.48.1