Commit 60544b69 authored by Andrew Gerrand's avatar Andrew Gerrand

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
parent 30ff0636
...@@ -148,13 +148,13 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -148,13 +148,13 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
// Find unresolved identifiers and uses of top-level declarations. // Find unresolved identifiers and uses of top-level declarations.
unresolved := make(map[string]bool) unresolved := make(map[string]bool)
usesTopDecl := false usesTopDecl := false
ast.Inspect(body, func(n ast.Node) bool { var inspectFunc func(ast.Node) bool
// For an expression like fmt.Println, only add "fmt" to the inspectFunc = func(n ast.Node) bool {
// set of unresolved names. // 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 e, ok := n.(*ast.SelectorExpr); ok {
if id, ok := e.X.(*ast.Ident); ok && id.Obj == nil { ast.Inspect(e.X, inspectFunc)
unresolved[id.Name] = true
}
return false return false
} }
if id, ok := n.(*ast.Ident); ok { if id, ok := n.(*ast.Ident); ok {
...@@ -165,7 +165,8 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -165,7 +165,8 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
} }
} }
return true return true
}) }
ast.Inspect(body, inspectFunc)
if usesTopDecl { if usesTopDecl {
// We don't support examples that are not self-contained (yet). // We don't support examples that are not self-contained (yet).
return nil return nil
......
// 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 = "<nil>"
} 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)
}
}
}
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