Commit 80dcc434 authored by Robert Griesemer's avatar Robert Griesemer

go/doc: fix identifier blank import handling for examples

Replacement CL for 6813061; thanks to minux for prototyping.

Fixes #4300.

R=minux.ma
CC=golang-dev
https://golang.org/cl/6782082
parent 792e664e
...@@ -356,6 +356,7 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File ...@@ -356,6 +356,7 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
// (use tabs, no comment highlight, etc). // (use tabs, no comment highlight, etc).
play := "" play := ""
if eg.Play != nil && *showPlayground { if eg.Play != nil && *showPlayground {
ast.SortImports(fset, eg.Play)
var buf bytes.Buffer var buf bytes.Buffer
err := (&printer.Config{Mode: printer.TabIndent, Tabwidth: 8}).Fprint(&buf, fset, eg.Play) err := (&printer.Config{Mode: printer.TabIndent, Tabwidth: 8}).Fprint(&buf, fset, eg.Play)
if err != nil { if err != nil {
......
...@@ -145,8 +145,9 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -145,8 +145,9 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
// Use unresolved identifiers to determine the imports used by this // Use unresolved identifiers to determine the imports used by this
// example. The heuristic assumes package names match base import // example. The heuristic assumes package names match base import
// paths. (Should be good enough most of the time.) // paths for imports w/o renames (should be good enough most of the time).
imports := make(map[string]string) // [name]path namedImports := make(map[string]string) // [name]path
var blankImports []ast.Spec // _ imports
for _, s := range file.Imports { for _, s := range file.Imports {
p, err := strconv.Unquote(s.Path.Value) p, err := strconv.Unquote(s.Path.Value)
if err != nil { if err != nil {
...@@ -154,14 +155,18 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -154,14 +155,18 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
} }
n := path.Base(p) n := path.Base(p)
if s.Name != nil { if s.Name != nil {
if s.Name.Name == "." { n = s.Name.Name
switch n {
case "_":
blankImports = append(blankImports, s)
continue
case ".":
// We can't resolve dot imports (yet). // We can't resolve dot imports (yet).
return nil return nil
} }
n = s.Name.Name
} }
if unresolved[n] { if unresolved[n] {
imports[n] = p namedImports[n] = p
delete(unresolved, n) delete(unresolved, n)
} }
} }
...@@ -172,13 +177,19 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -172,13 +177,19 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
return nil return nil
} }
// Filter out comments that are outside the function body. // Include documentation belonging to blank imports.
var comments []*ast.CommentGroup var comments []*ast.CommentGroup
for _, s := range blankImports {
if c := s.(*ast.ImportSpec).Doc; c != nil {
comments = append(comments, c)
}
}
// Include comments that are inside the function body.
for _, c := range file.Comments { for _, c := range file.Comments {
if c.Pos() < body.Pos() || c.Pos() >= body.End() { if body.Pos() <= c.Pos() && c.End() <= body.End() {
continue comments = append(comments, c)
} }
comments = append(comments, c)
} }
// Strip "Output:" commment and adjust body end position. // Strip "Output:" commment and adjust body end position.
...@@ -190,13 +201,14 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -190,13 +201,14 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
Lparen: 1, // Need non-zero Lparen and Rparen so that printer Lparen: 1, // Need non-zero Lparen and Rparen so that printer
Rparen: 1, // treats this as a factored import. Rparen: 1, // treats this as a factored import.
} }
for n, p := range imports { for n, p := range namedImports {
s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}} s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
if path.Base(p) != n { if path.Base(p) != n {
s.Name = ast.NewIdent(n) s.Name = ast.NewIdent(n)
} }
importDecl.Specs = append(importDecl.Specs, s) importDecl.Specs = append(importDecl.Specs, s)
} }
importDecl.Specs = append(importDecl.Specs, blankImports...)
// Synthesize main function. // Synthesize main function.
funcDecl := &ast.FuncDecl{ funcDecl := &ast.FuncDecl{
...@@ -213,7 +225,7 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { ...@@ -213,7 +225,7 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
} }
} }
// playExample takes a whole file example and synthesizes a new *ast.File // playExampleFile takes a whole file example and synthesizes a new *ast.File
// such that the example is function main in package main. // such that the example is function main in package main.
func playExampleFile(file *ast.File) *ast.File { func playExampleFile(file *ast.File) *ast.File {
// Strip copyright comment if present. // Strip copyright comment if present.
......
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