Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1183)

Delta Between Two Patch Sets: src/pkg/go/doc/example.go

Issue 7127064: doc: Do not sort by test examples by name. (Closed)
Left Patch Set: Created 11 years, 2 months ago
Right Patch Set: diff -r 8516cee2bf33 https://code.google.com/p/go Created 11 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Extract example functions from file ASTs. 5 // Extract example functions from file ASTs.
6 6
7 package doc 7 package doc
8 8
9 import ( 9 import (
10 "go/ast" 10 "go/ast"
11 "go/token" 11 "go/token"
12 "path" 12 "path"
13 "regexp" 13 "regexp"
14 "sort"
15 "strconv" 14 "strconv"
16 "strings" 15 "strings"
17 "unicode" 16 "unicode"
18 "unicode/utf8" 17 "unicode/utf8"
19 ) 18 )
20 19
21 type Example struct { 20 type Example struct {
22 Name string // name of the item being exemplified 21 Name string // name of the item being exemplified
23 Doc string // example function doc string 22 Doc string // example function doc string
24 Code ast.Node 23 Code ast.Node
25 Play *ast.File // a whole program version of the example 24 Play *ast.File // a whole program version of the example
26 Comments []*ast.CommentGroup 25 Comments []*ast.CommentGroup
27 Output string // expected output 26 Output string // expected output
28 EmptyOutput bool // expect empty output 27 EmptyOutput bool // expect empty output
28 Order int // original source order
29 } 29 }
30 30
31 func Examples(files ...*ast.File) []*Example { 31 func Examples(files ...*ast.File) []*Example {
32 var list []*Example 32 var list []*Example
33 » for _, file := range files { 33 » for i, file := range files {
34 hasTests := false // file contains tests or benchmarks 34 hasTests := false // file contains tests or benchmarks
35 numDecl := 0 // number of non-import declarations in the fi le 35 numDecl := 0 // number of non-import declarations in the fi le
36 var flist []*Example 36 var flist []*Example
37 for _, decl := range file.Decls { 37 for _, decl := range file.Decls {
38 if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IM PORT { 38 if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IM PORT {
39 numDecl++ 39 numDecl++
40 continue 40 continue
41 } 41 }
42 f, ok := decl.(*ast.FuncDecl) 42 f, ok := decl.(*ast.FuncDecl)
43 if !ok { 43 if !ok {
(...skipping 14 matching lines...) Expand all
58 } 58 }
59 output, hasOutput := exampleOutput(f.Body, file.Comments ) 59 output, hasOutput := exampleOutput(f.Body, file.Comments )
60 flist = append(flist, &Example{ 60 flist = append(flist, &Example{
61 Name: name[len("Example"):], 61 Name: name[len("Example"):],
62 Doc: doc, 62 Doc: doc,
63 Code: f.Body, 63 Code: f.Body,
64 Play: playExample(file, f.Body), 64 Play: playExample(file, f.Body),
65 Comments: file.Comments, 65 Comments: file.Comments,
66 Output: output, 66 Output: output,
67 EmptyOutput: output == "" && hasOutput, 67 EmptyOutput: output == "" && hasOutput,
68 Order: i,
68 }) 69 })
69 } 70 }
70 if !hasTests && numDecl > 1 && len(flist) == 1 { 71 if !hasTests && numDecl > 1 && len(flist) == 1 {
71 // If this file only has one example function, some 72 // If this file only has one example function, some
72 // other top-level declarations, and no tests or 73 // other top-level declarations, and no tests or
73 // benchmarks, use the whole file as the example. 74 // benchmarks, use the whole file as the example.
74 flist[0].Code = file 75 flist[0].Code = file
75 flist[0].Play = playExampleFile(file) 76 flist[0].Play = playExampleFile(file)
76 } 77 }
77 list = append(list, flist...) 78 list = append(list, flist...)
78 } 79 }
79 sort.Sort(exampleByName(list))
80 return list 80 return list
81 } 81 }
82 82
83 var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`) 83 var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)
84 84
85 // Extracts the expected output and whether there was a valid output comment 85 // Extracts the expected output and whether there was a valid output comment
86 func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output strin g, ok bool) { 86 func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output strin g, ok bool) {
87 if _, last := lastComment(b, comments); last != nil { 87 if _, last := lastComment(b, comments); last != nil {
88 // test that it begins with the correct prefix 88 // test that it begins with the correct prefix
89 text := last.Text() 89 text := last.Text()
(...skipping 16 matching lines...) Expand all
106 func isTest(name, prefix string) bool { 106 func isTest(name, prefix string) bool {
107 if !strings.HasPrefix(name, prefix) { 107 if !strings.HasPrefix(name, prefix) {
108 return false 108 return false
109 } 109 }
110 if len(name) == len(prefix) { // "Test" is ok 110 if len(name) == len(prefix) { // "Test" is ok
111 return true 111 return true
112 } 112 }
113 rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) 113 rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
114 return !unicode.IsLower(rune) 114 return !unicode.IsLower(rune)
115 } 115 }
116
117 type exampleByName []*Example
118
119 func (s exampleByName) Len() int { return len(s) }
120 func (s exampleByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
121 func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
122 116
123 // playExample synthesizes a new *ast.File based on the provided 117 // playExample synthesizes a new *ast.File based on the provided
124 // file with the provided function body as the body of main. 118 // file with the provided function body as the body of main.
125 func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { 119 func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
126 if !strings.HasSuffix(file.Name.Name, "_test") { 120 if !strings.HasSuffix(file.Name.Name, "_test") {
127 // We don't support examples that are part of the 121 // We don't support examples that are part of the
128 // greater package (yet). 122 // greater package (yet).
129 return nil 123 return nil
130 } 124 }
131 125
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 if cg.Pos() < pos { 317 if cg.Pos() < pos {
324 continue 318 continue
325 } 319 }
326 if cg.End() > end { 320 if cg.End() > end {
327 break 321 break
328 } 322 }
329 i, last = j, cg 323 i, last = j, cg
330 } 324 }
331 return 325 return
332 } 326 }
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b