Left: | ||
Right: |
OLD | NEW |
---|---|
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" |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 // Remove predeclared identifiers from unresolved list. | 139 // Remove predeclared identifiers from unresolved list. |
140 for n := range unresolved { | 140 for n := range unresolved { |
141 if predeclaredTypes[n] || predeclaredConstants[n] || predeclared Funcs[n] { | 141 if predeclaredTypes[n] || predeclaredConstants[n] || predeclared Funcs[n] { |
142 delete(unresolved, n) | 142 delete(unresolved, n) |
143 } | 143 } |
144 } | 144 } |
145 | 145 |
146 // Use unresolved identifiers to determine the imports used by this | 146 // Use unresolved identifiers to determine the imports used by this |
147 // example. The heuristic assumes package names match base import | 147 // example. The heuristic assumes package names match base import |
148 // paths. (Should be good enough most of the time.) | 148 // paths. (Should be good enough most of the time.) |
149 » imports := make(map[string]string) // [name]path | 149 » imports := make(map[string]string) // [name]path |
gri
2012/11/16 19:52:23
Please call the first map say "namedImports" so it
| |
150 » blankImports := []*ast.ImportSpec{} // _ imports | |
150 for _, s := range file.Imports { | 151 for _, s := range file.Imports { |
151 p, err := strconv.Unquote(s.Path.Value) | 152 p, err := strconv.Unquote(s.Path.Value) |
152 if err != nil { | 153 if err != nil { |
153 continue | 154 continue |
154 } | 155 } |
155 n := path.Base(p) | 156 n := path.Base(p) |
156 if s.Name != nil { | 157 if s.Name != nil { |
157 if s.Name.Name == "." { | 158 if s.Name.Name == "." { |
158 // We can't resolve dot imports (yet). | 159 // We can't resolve dot imports (yet). |
159 return nil | 160 return nil |
160 } | 161 } |
161 n = s.Name.Name | 162 n = s.Name.Name |
162 } | 163 } |
163 if unresolved[n] { | 164 if unresolved[n] { |
164 imports[n] = p | 165 imports[n] = p |
165 delete(unresolved, n) | 166 delete(unresolved, n) |
166 } | 167 } |
168 if n == "_" { | |
gri
2012/11/16 19:52:23
This should be "else if", but better:
switch {
ca
| |
169 blankImports = append(blankImports, s) | |
170 } | |
167 } | 171 } |
168 | 172 |
169 // If there are other unresolved identifiers, give up because this | 173 // If there are other unresolved identifiers, give up because this |
170 // synthesized file is not going to build. | 174 // synthesized file is not going to build. |
171 if len(unresolved) > 0 { | 175 if len(unresolved) > 0 { |
172 return nil | 176 return nil |
173 } | 177 } |
174 | 178 |
175 // Filter out comments that are outside the function body. | 179 // Filter out comments that are outside the function body. |
gri
2012/11/16 19:52:23
This is too complicated. The comments associated w
| |
176 var comments []*ast.CommentGroup | 180 var comments []*ast.CommentGroup |
177 for _, c := range file.Comments { | 181 for _, c := range file.Comments { |
178 » » if c.Pos() < body.Pos() || c.Pos() >= body.End() { | 182 » » incl := false |
179 » » » continue | 183 » » for _, p := range blankImports { |
adg
2012/11/13 11:50:48
I think this code is getting complex enough that w
minux1
2012/11/15 11:04:09
Will do that after I figure out why the formatting
| |
184 » » » if p.Doc != nil && c.Pos() >= p.Doc.Pos() && c.Pos() < p .Doc.End() { | |
185 » » » » incl = true | |
186 » » » » break | |
187 » » » } | |
180 } | 188 } |
181 » » comments = append(comments, c) | 189 » » if c.Pos() >= body.Pos() && c.Pos() < body.End() { |
190 » » » incl = true | |
191 » » } | |
192 » » if incl { | |
193 » » » comments = append(comments, c) | |
194 » » } | |
182 } | 195 } |
183 | 196 |
184 // Strip "Output:" commment and adjust body end position. | 197 // Strip "Output:" commment and adjust body end position. |
185 body, comments = stripOutputComment(body, comments) | 198 body, comments = stripOutputComment(body, comments) |
186 | 199 |
187 // Synthesize import declaration. | 200 // Synthesize import declaration. |
188 importDecl := &ast.GenDecl{ | 201 importDecl := &ast.GenDecl{ |
189 Tok: token.IMPORT, | 202 Tok: token.IMPORT, |
190 Lparen: 1, // Need non-zero Lparen and Rparen so that printer | 203 Lparen: 1, // Need non-zero Lparen and Rparen so that printer |
191 Rparen: 1, // treats this as a factored import. | 204 Rparen: 1, // treats this as a factored import. |
192 } | 205 } |
193 for n, p := range imports { | 206 for n, p := range imports { |
gri
2012/11/16 19:52:23
s/imports/namedImports/
| |
194 s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p) }} | 207 s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p) }} |
195 if path.Base(p) != n { | 208 if path.Base(p) != n { |
196 s.Name = ast.NewIdent(n) | 209 s.Name = ast.NewIdent(n) |
197 } | 210 } |
198 importDecl.Specs = append(importDecl.Specs, s) | 211 importDecl.Specs = append(importDecl.Specs, s) |
199 } | 212 } |
213 for _, p := range blankImports { | |
gri
2012/11/16 19:52:23
this becomes:
importDecl.Specs = append(importDec
| |
214 importDecl.Specs = append(importDecl.Specs, p) | |
215 } | |
200 | 216 |
201 // Synthesize main function. | 217 // Synthesize main function. |
202 funcDecl := &ast.FuncDecl{ | 218 funcDecl := &ast.FuncDecl{ |
203 Name: ast.NewIdent("main"), | 219 Name: ast.NewIdent("main"), |
204 Type: &ast.FuncType{}, | 220 Type: &ast.FuncType{}, |
205 Body: body, | 221 Body: body, |
206 } | 222 } |
207 | 223 |
208 // Synthesize file. | 224 // Synthesize file. |
209 return &ast.File{ | 225 return &ast.File{ |
210 Name: ast.NewIdent("main"), | 226 Name: ast.NewIdent("main"), |
211 Decls: []ast.Decl{importDecl, funcDecl}, | 227 Decls: []ast.Decl{importDecl, funcDecl}, |
212 Comments: comments, | 228 Comments: comments, |
213 } | 229 } |
214 } | 230 } |
215 | 231 |
216 // playExample takes a whole file example and synthesizes a new *ast.File | 232 // playExampleFile takes a whole file example and synthesizes a new *ast.File |
217 // such that the example is function main in package main. | 233 // such that the example is function main in package main. |
218 func playExampleFile(file *ast.File) *ast.File { | 234 func playExampleFile(file *ast.File) *ast.File { |
219 // Strip copyright comment if present. | 235 // Strip copyright comment if present. |
220 comments := file.Comments | 236 comments := file.Comments |
221 if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright ") { | 237 if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright ") { |
222 comments = comments[1:] | 238 comments = comments[1:] |
223 } | 239 } |
224 | 240 |
225 // Copy declaration slice, rewriting the ExampleX function to main. | 241 // Copy declaration slice, rewriting the ExampleX function to main. |
226 var decls []ast.Decl | 242 var decls []ast.Decl |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 if cg.Pos() < pos { | 287 if cg.Pos() < pos { |
272 continue | 288 continue |
273 } | 289 } |
274 if cg.End() > end { | 290 if cg.End() > end { |
275 break | 291 break |
276 } | 292 } |
277 i, last = j, cg | 293 i, last = j, cg |
278 } | 294 } |
279 return | 295 return |
280 } | 296 } |
OLD | NEW |