Permalink
Browse files

Subtree merged in lang/

  • Loading branch information...
fd committed Feb 19, 2013
2 parents d81a903 + c99e8d2 commit 36921a033afdebaab68b3638ee0b972de57cc6a9
Showing with 61,104 additions and 0 deletions.
  1. +1,021 −0 lang/ast/ast.go
  2. +50 −0 lang/ast/ast_test.go
  3. +332 −0 lang/ast/commentmap.go
  4. +143 −0 lang/ast/commentmap_test.go
  5. +136 −0 lang/ast/example_test.go
  6. +460 −0 lang/ast/filter.go
  7. +134 −0 lang/ast/import.go
  8. +251 −0 lang/ast/print.go
  9. +97 −0 lang/ast/print_test.go
  10. +367 −0 lang/ast/replace.go
  11. +174 −0 lang/ast/resolve.go
  12. +162 −0 lang/ast/scope.go
  13. +391 −0 lang/ast/walk.go
  14. +1,053 −0 lang/build/build.go
  15. +119 −0 lang/build/build_test.go
  16. +431 −0 lang/build/deps_test.go
  17. +120 −0 lang/build/doc.go
  18. +238 −0 lang/build/read.go
  19. +226 −0 lang/build/read_test.go
  20. +8 −0 lang/build/syslist.go
  21. +62 −0 lang/build/syslist_test.go
  22. +5 −0 lang/build/testdata/other/file/file.go
  23. +11 −0 lang/build/testdata/other/main.go
  24. +30 −0 lang/cmd/sx/bootstrap.go
  25. +1,930 −0 lang/cmd/sx/build.go
  26. +225 −0 lang/cmd/sx/clean.go
  27. +63 −0 lang/cmd/sx/discovery.go
  28. +797 −0 lang/cmd/sx/doc.go
  29. +91 −0 lang/cmd/sx/env.go
  30. +30 −0 lang/cmd/sx/fix.go
  31. +73 −0 lang/cmd/sx/fmt.go
  32. +400 −0 lang/cmd/sx/get.go
  33. +238 −0 lang/cmd/sx/help.go
  34. +87 −0 lang/cmd/sx/http.go
  35. +171 −0 lang/cmd/sx/list.go
  36. +568 −0 lang/cmd/sx/main.go
  37. +36 −0 lang/cmd/sx/match_test.go
  38. +8 −0 lang/cmd/sx/mkdoc.sh
  39. +737 −0 lang/cmd/sx/pkg.go
  40. +91 −0 lang/cmd/sx/run.go
  41. +23 −0 lang/cmd/sx/script
  42. +352 −0 lang/cmd/sx/script.txt
  43. +31 −0 lang/cmd/sx/signal.go
  44. +13 −0 lang/cmd/sx/signal_notunix.go
  45. +14 −0 lang/cmd/sx/signal_unix.go
  46. +100 −0 lang/cmd/sx/tag_test.go
  47. +193 −0 lang/cmd/sx/test.bash
  48. +859 −0 lang/cmd/sx/test.go
  49. +3 −0 lang/cmd/sx/testdata/errmsg/x.go
  50. +3 −0 lang/cmd/sx/testdata/errmsg/x1_test.go
  51. +3 −0 lang/cmd/sx/testdata/errmsg/x_test.go
  52. +7 −0 lang/cmd/sx/testdata/local/easy.go
  53. +7 −0 lang/cmd/sx/testdata/local/easysub/easysub.go
  54. +9 −0 lang/cmd/sx/testdata/local/easysub/main.go
  55. +7 −0 lang/cmd/sx/testdata/local/hard.go
  56. +12 −0 lang/cmd/sx/testdata/local/sub/sub.go
  57. +7 −0 lang/cmd/sx/testdata/local/sub/sub/subsub.go
  58. +5 −0 lang/cmd/sx/testdata/src/go-cmd-test/helloworld.go
  59. +3 −0 lang/cmd/sx/testdata/testimport/p.go
  60. +3 −0 lang/cmd/sx/testdata/testimport/p1/p1.go
  61. +3 −0 lang/cmd/sx/testdata/testimport/p2/p2.go
  62. +13 −0 lang/cmd/sx/testdata/testimport/p_test.go
  63. +15 −0 lang/cmd/sx/testdata/testimport/x_test.go
  64. +242 −0 lang/cmd/sx/testflag.go
  65. +135 −0 lang/cmd/sx/tool.go
  66. +678 −0 lang/cmd/sx/vcs.go
  67. +25 −0 lang/cmd/sx/version.go
  68. +37 −0 lang/cmd/sx/vet.go
  69. +52 −0 lang/cmd/sxc/main.go
  70. +61 −0 lang/cmd/sxdoc/README.godoc-app
  71. +69 −0 lang/cmd/sxdoc/appinit.go
  72. +494 −0 lang/cmd/sxdoc/codewalk.go
  73. +329 −0 lang/cmd/sxdoc/dirtrees.go
  74. +130 −0 lang/cmd/sxdoc/doc.go
  75. +564 −0 lang/cmd/sxdoc/filesystem.go
  76. +360 −0 lang/cmd/sxdoc/format.go
  77. +1,512 −0 lang/cmd/sxdoc/godoc.go
  78. +1,075 −0 lang/cmd/sxdoc/index.go
  79. +466 −0 lang/cmd/sxdoc/main.go
  80. +68 −0 lang/cmd/sxdoc/parser.go
  81. +35 −0 lang/cmd/sxdoc/play-appengine.go
  82. +41 −0 lang/cmd/sxdoc/play-local.go
  83. +52 −0 lang/cmd/sxdoc/play.go
  84. +140 −0 lang/cmd/sxdoc/setup-godoc-app.bash
  85. +112 −0 lang/cmd/sxdoc/snippet.go
  86. +179 −0 lang/cmd/sxdoc/spec.go
  87. +182 −0 lang/cmd/sxdoc/template.go
  88. +88 −0 lang/cmd/sxdoc/throttle.go
  89. +93 −0 lang/cmd/sxdoc/utils.go
  90. +236 −0 lang/cmd/sxdoc/zip.go
  91. +77 −0 lang/cmd/sxfmt/doc.go
  92. +361 −0 lang/cmd/sxfmt/gofmt.go
  93. +361 −0 lang/cmd/sxfmt/gofmt.go.gofmt
  94. +132 −0 lang/cmd/sxfmt/gofmt_test.go
  95. +132 −0 lang/cmd/sxfmt/gofmt_test.go.gofmt
  96. +159 −0 lang/cmd/sxfmt/long_test.go
  97. +295 −0 lang/cmd/sxfmt/rewrite.go
  98. +117 −0 lang/cmd/sxfmt/simplify.go
  99. +4 −0 lang/cmd/sxfmt/testdata/.gitattributes
  100. +9 −0 lang/cmd/sxfmt/testdata/comments.golden
  101. +9 −0 lang/cmd/sxfmt/testdata/comments.input
  102. +202 −0 lang/cmd/sxfmt/testdata/composites.golden
  103. +202 −0 lang/cmd/sxfmt/testdata/composites.input
  104. +12 −0 lang/cmd/sxfmt/testdata/crlf.golden
  105. +12 −0 lang/cmd/sxfmt/testdata/crlf.input
  106. +108 −0 lang/cmd/sxfmt/testdata/import.golden
  107. +108 −0 lang/cmd/sxfmt/testdata/import.input
  108. +9 −0 lang/cmd/sxfmt/testdata/old.golden
  109. +8 −0 lang/cmd/sxfmt/testdata/old.input
  110. +12 −0 lang/cmd/sxfmt/testdata/rewrite1.golden
  111. +12 −0 lang/cmd/sxfmt/testdata/rewrite1.input
  112. +10 −0 lang/cmd/sxfmt/testdata/rewrite2.golden
  113. +10 −0 lang/cmd/sxfmt/testdata/rewrite2.input
  114. +12 −0 lang/cmd/sxfmt/testdata/rewrite3.golden
  115. +12 −0 lang/cmd/sxfmt/testdata/rewrite3.input
  116. +74 −0 lang/cmd/sxfmt/testdata/rewrite4.golden
  117. +74 −0 lang/cmd/sxfmt/testdata/rewrite4.input
  118. +15 −0 lang/cmd/sxfmt/testdata/rewrite5.golden
  119. +15 −0 lang/cmd/sxfmt/testdata/rewrite5.input
  120. +58 −0 lang/cmd/sxfmt/testdata/slices1.golden
  121. +58 −0 lang/cmd/sxfmt/testdata/slices1.input
  122. +61 −0 lang/cmd/sxfmt/testdata/slices2.golden
  123. +61 −0 lang/cmd/sxfmt/testdata/slices2.input
  124. +3 −0 lang/cmd/sxfmt/testdata/stdin1.golden
  125. +3 −0 lang/cmd/sxfmt/testdata/stdin1.golden.gofmt
  126. +3 −0 lang/cmd/sxfmt/testdata/stdin1.input
  127. +3 −0 lang/cmd/sxfmt/testdata/stdin1.input.gofmt
  128. +11 −0 lang/cmd/sxfmt/testdata/stdin2.golden
  129. +10 −0 lang/cmd/sxfmt/testdata/stdin2.golden.gofmt
  130. +11 −0 lang/cmd/sxfmt/testdata/stdin2.input
  131. +11 −0 lang/cmd/sxfmt/testdata/stdin2.input.gofmt
  132. +6 −0 lang/cmd/sxfmt/testdata/stdin3.golden
  133. +7 −0 lang/cmd/sxfmt/testdata/stdin3.golden.gofmt
  134. +4 −0 lang/cmd/sxfmt/testdata/stdin3.input
  135. +7 −0 lang/cmd/sxfmt/testdata/stdin3.input.gofmt
  136. +3 −0 lang/cmd/sxfmt/testdata/stdin4.golden
  137. +3 −0 lang/cmd/sxfmt/testdata/stdin4.golden.gofmt
  138. +3 −0 lang/cmd/sxfmt/testdata/stdin4.input
  139. +3 −0 lang/cmd/sxfmt/testdata/stdin4.input.gofmt
  140. +60 −0 lang/cmd/sxfmt/testdata/typeswitch.golden
  141. +60 −0 lang/cmd/sxfmt/testdata/typeswitch.input
  142. +54 −0 lang/compiler/context.go
  143. +832 −0 lang/compiler/converter.go
  144. +60 −0 lang/compiler/hasher.go
  145. +30 −0 lang/compiler/parser.go
  146. +320 −0 lang/compiler/printer.go
  147. +108 −0 lang/compiler/type_checker.go
  148. +465 −0 lang/compiler/type_printer.go
  149. +12 −0 lang/compiler/types.go
  150. +7 −0 lang/doc/Makefile
  151. +442 −0 lang/doc/comment.go
  152. +109 −0 lang/doc/comment_test.go
  153. +97 −0 lang/doc/doc.go
  154. +136 −0 lang/doc/doc_test.go
  155. +332 −0 lang/doc/example.go
  156. +111 −0 lang/doc/example_test.go
  157. +199 −0 lang/doc/exports.go
  158. +105 −0 lang/doc/filter.go
  159. +113 −0 lang/doc/headscan.go
  160. +802 −0 lang/doc/reader.go
  161. +73 −0 lang/doc/synopsis.go
  162. +49 −0 lang/doc/synopsis_test.go
  163. +13 −0 lang/doc/testdata/a.0.golden
  164. +13 −0 lang/doc/testdata/a.1.golden
  165. +13 −0 lang/doc/testdata/a.2.golden
  166. +8 −0 lang/doc/testdata/a0.go
  167. +8 −0 lang/doc/testdata/a1.go
  168. +71 −0 lang/doc/testdata/b.0.golden
  169. +83 −0 lang/doc/testdata/b.1.golden
  170. +71 −0 lang/doc/testdata/b.2.golden
  171. +58 −0 lang/doc/testdata/b.go
  172. +293 −0 lang/doc/testdata/benchmark.go
  173. +48 −0 lang/doc/testdata/c.0.golden
  174. +48 −0 lang/doc/testdata/c.1.golden
  175. +48 −0 lang/doc/testdata/c.2.golden
  176. +62 −0 lang/doc/testdata/c.go
  177. +104 −0 lang/doc/testdata/d.0.golden
  178. +104 −0 lang/doc/testdata/d.1.golden
  179. +104 −0 lang/doc/testdata/d.2.golden
  180. +57 −0 lang/doc/testdata/d1.go
  181. +45 −0 lang/doc/testdata/d2.go
  182. +109 −0 lang/doc/testdata/e.0.golden
  183. +144 −0 lang/doc/testdata/e.1.golden
  184. +130 −0 lang/doc/testdata/e.2.golden
  185. +147 −0 lang/doc/testdata/e.go
  186. +30 −0 lang/doc/testdata/error1.0.golden
  187. +32 −0 lang/doc/testdata/error1.1.golden
  188. +30 −0 lang/doc/testdata/error1.2.golden
  189. +24 −0 lang/doc/testdata/error1.go
  190. +27 −0 lang/doc/testdata/error2.0.golden
  191. +37 −0 lang/doc/testdata/error2.1.golden
  192. +27 −0 lang/doc/testdata/error2.2.golden
  193. +29 −0 lang/doc/testdata/error2.go
  194. +81 −0 lang/doc/testdata/example.go
  195. +13 −0 lang/doc/testdata/f.0.golden
  196. +16 −0 lang/doc/testdata/f.1.golden
  197. +13 −0 lang/doc/testdata/f.2.golden
  198. +14 −0 lang/doc/testdata/f.go
  199. +65 −0 lang/doc/testdata/template.txt
  200. +156 −0 lang/doc/testdata/testing.0.golden
  201. +298 −0 lang/doc/testdata/testing.1.golden
  202. +156 −0 lang/doc/testdata/testing.2.golden
  203. +404 −0 lang/doc/testdata/testing.go
  204. +200 −0 lang/format/format.go
  205. +126 −0 lang/format/format_test.go
  206. +166 −0 lang/parser/error_test.go
  207. +34 −0 lang/parser/example_test.go
  208. +174 −0 lang/parser/interface.go
  209. +2,453 −0 lang/parser/parser.go
  210. +411 −0 lang/parser/parser_test.go
  211. +30 −0 lang/parser/performance_test.go
  212. +80 −0 lang/parser/short_test.go
  213. +19 −0 lang/parser/testdata/commas.src
  214. +46 −0 lang/parser/testdata/issue3106.src
  215. +67 −0 lang/printer/example_test.go
  216. +1,591 −0 lang/printer/nodes.go
  217. +58 −0 lang/printer/performance_test.go
  218. +1,262 −0 lang/printer/printer.go
  219. +569 −0 lang/printer/printer_test.go
  220. +638 −0 lang/printer/testdata/comments.golden
  221. +642 −0 lang/printer/testdata/comments.input
  222. +56 −0 lang/printer/testdata/comments.x
  223. +79 −0 lang/printer/testdata/comments2.golden
  224. +79 −0 lang/printer/testdata/comments2.input
  225. +914 −0 lang/printer/testdata/declarations.golden
  226. +923 −0 lang/printer/testdata/declarations.input
  227. +5 −0 lang/printer/testdata/empty.golden
  228. +5 −0 lang/printer/testdata/empty.input
  229. +664 −0 lang/printer/testdata/expressions.golden
  230. +693 −0 lang/printer/testdata/expressions.input
  231. +664 −0 lang/printer/testdata/expressions.raw
  232. +275 −0 lang/printer/testdata/linebreaks.golden
  233. +271 −0 lang/printer/testdata/linebreaks.input
  234. +2,153 −0 lang/printer/testdata/parser.go
  235. +85 −0 lang/printer/testdata/slow.golden
  236. +85 −0 lang/printer/testdata/slow.input
  237. +635 −0 lang/printer/testdata/statements.golden
  238. +550 −0 lang/printer/testdata/statements.input
  239. +126 −0 lang/scanner/errors.go
  240. +46 −0 lang/scanner/example_test.go
  241. +727 −0 lang/scanner/scanner.go
  242. +755 −0 lang/scanner/scanner_test.go
  243. +437 −0 lang/token/position.go
  244. +232 −0 lang/token/position_test.go
  245. +56 −0 lang/token/serialize.go
  246. +111 −0 lang/token/serialize_test.go
  247. +318 −0 lang/token/token.go
  248. +96 −0 lang/types/api.go
  249. +465 −0 lang/types/builtins.go
  250. +454 −0 lang/types/check.go
  251. +261 −0 lang/types/check_test.go
  252. +734 −0 lang/types/const.go
  253. +41 −0 lang/types/conversions.go
  254. +334 −0 lang/types/errors.go
  255. +111 −0 lang/types/exportdata.go
  256. +1,665 −0 lang/types/expr.go
  257. +908 −0 lang/types/gcimporter.go
  258. +181 −0 lang/types/gcimporter_test.go
  259. +155 −0 lang/types/objects.go
  260. +463 −0 lang/types/operand.go
  261. +324 −0 lang/types/predicates.go
  262. +177 −0 lang/types/resolve.go
  263. +167 −0 lang/types/resolver_test.go
  264. +59 −0 lang/types/scope.go
  265. +721 −0 lang/types/stmt.go
  266. +302 −0 lang/types/testdata/builtins.src
  267. +27 −0 lang/types/testdata/builtins_sx.src
  268. +215 −0 lang/types/testdata/const0.src
  269. +18 −0 lang/types/testdata/conversions.src
  270. +36 −0 lang/types/testdata/conversions_sx.src
  271. +177 −0 lang/types/testdata/decls0.src
  272. +132 −0 lang/types/testdata/decls1.src
  273. +67 −0 lang/types/testdata/decls2a.src
  274. +28 −0 lang/types/testdata/decls2b.src
  275. +231 −0 lang/types/testdata/decls3.src
  276. +89 −0 lang/types/testdata/exports.go
  277. +151 −0 lang/types/testdata/expr0.src
  278. +156 −0 lang/types/testdata/expr0_sx.src
  279. +7 −0 lang/types/testdata/expr1.src
  280. +23 −0 lang/types/testdata/expr2.src
  281. +367 −0 lang/types/testdata/expr3.src
  282. +274 −0 lang/types/testdata/stmt0.src
  283. +258 −0 lang/types/types.go
  284. +175 −0 lang/types/types_test.go
  285. +138 −0 lang/types/universe.go
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,50 @@
+// Copyright 2012 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 ast
+
+import (
+ "testing"
+)
+
+var comments = []struct {
+ list []string
+ text string
+}{
+ {[]string{"//"}, ""},
+ {[]string{"// "}, ""},
+ {[]string{"//", "//", "// "}, ""},
+ {[]string{"// foo "}, "foo\n"},
+ {[]string{"//", "//", "// foo"}, "foo\n"},
+ {[]string{"// foo bar "}, "foo bar\n"},
+ {[]string{"// foo", "// bar"}, "foo\nbar\n"},
+ {[]string{"// foo", "//", "//", "//", "// bar"}, "foo\n\nbar\n"},
+ {[]string{"// foo", "/* bar */"}, "foo\n bar\n"},
+ {[]string{"//", "//", "//", "// foo", "//", "//", "//"}, "foo\n"},
+
+ {[]string{"/**/"}, ""},
+ {[]string{"/* */"}, ""},
+ {[]string{"/**/", "/**/", "/* */"}, ""},
+ {[]string{"/* Foo */"}, " Foo\n"},
+ {[]string{"/* Foo Bar */"}, " Foo Bar\n"},
+ {[]string{"/* Foo*/", "/* Bar*/"}, " Foo\n Bar\n"},
+ {[]string{"/* Foo*/", "/**/", "/**/", "/**/", "// Bar"}, " Foo\n\nBar\n"},
+ {[]string{"/* Foo*/", "/*\n*/", "//", "/*\n*/", "// Bar"}, " Foo\n\nBar\n"},
+ {[]string{"/* Foo*/", "// Bar"}, " Foo\nBar\n"},
+ {[]string{"/* Foo\n Bar*/"}, " Foo\n Bar\n"},
+}
+
+func TestCommentText(t *testing.T) {
+ for i, c := range comments {
+ list := make([]*Comment, len(c.list))
+ for i, s := range c.list {
+ list[i] = &Comment{Text: s}
+ }
+
+ text := (&CommentGroup{list}).Text()
+ if text != c.text {
+ t.Errorf("case %d: got %q; expected %q", i, text, c.text)
+ }
+ }
+}
View
@@ -0,0 +1,332 @@
+// Copyright 2012 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 ast
+
+import (
+ "bytes"
+ "fmt"
+ "simplex.sh/lang/token"
+ "sort"
+)
+
+type byPos []*CommentGroup
+
+func (a byPos) Len() int { return len(a) }
+func (a byPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byPos) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// sortComments sorts the list of comment groups in source order.
+//
+func sortComments(list []*CommentGroup) {
+ // TODO(gri): Does it make sense to check for sorted-ness
+ // first (because we know that sorted-ness is
+ // very likely)?
+ if orderedList := byPos(list); !sort.IsSorted(orderedList) {
+ sort.Sort(orderedList)
+ }
+}
+
+// A CommentMap maps an AST node to a list of comment groups
+// associated with it. See NewCommentMap for a description of
+// the association.
+//
+type CommentMap map[Node][]*CommentGroup
+
+func (cmap CommentMap) addComment(n Node, c *CommentGroup) {
+ list := cmap[n]
+ if len(list) == 0 {
+ list = []*CommentGroup{c}
+ } else {
+ list = append(list, c)
+ }
+ cmap[n] = list
+}
+
+type byInterval []Node
+
+func (a byInterval) Len() int { return len(a) }
+func (a byInterval) Less(i, j int) bool {
+ pi, pj := a[i].Pos(), a[j].Pos()
+ return pi < pj || pi == pj && a[i].End() > a[j].End()
+}
+func (a byInterval) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// nodeList returns the list of nodes of the AST n in source order.
+//
+func nodeList(n Node) []Node {
+ var list []Node
+ Inspect(n, func(n Node) bool {
+ // don't collect comments
+ switch n.(type) {
+ case nil, *CommentGroup, *Comment:
+ return false
+ }
+ list = append(list, n)
+ return true
+ })
+ // Note: The current implementation assumes that Inspect traverses the
+ // AST in depth-first and thus _source_ order. If AST traversal
+ // does not follow source order, the sorting call below will be
+ // required.
+ // sort.Sort(byInterval(list))
+ return list
+}
+
+// A commentListReader helps iterating through a list of comment groups.
+//
+type commentListReader struct {
+ fset *token.FileSet
+ list []*CommentGroup
+ index int
+ comment *CommentGroup // comment group at current index
+ pos, end token.Position // source interval of comment group at current index
+}
+
+func (r *commentListReader) eol() bool {
+ return r.index >= len(r.list)
+}
+
+func (r *commentListReader) next() {
+ if !r.eol() {
+ r.comment = r.list[r.index]
+ r.pos = r.fset.Position(r.comment.Pos())
+ r.end = r.fset.Position(r.comment.End())
+ r.index++
+ }
+}
+
+// A nodeStack keeps track of nested nodes.
+// A node lower on the stack lexically contains the nodes higher on the stack.
+//
+type nodeStack []Node
+
+// push pops all nodes that appear lexically before n
+// and then pushes n on the stack.
+//
+func (s *nodeStack) push(n Node) {
+ s.pop(n.Pos())
+ *s = append(*s, n)
+}
+
+// pop pops all nodes that appear lexically before pos
+// (i.e., whose lexical extent has ended before or at pos).
+// It returns the last node popped.
+//
+func (s *nodeStack) pop(pos token.Pos) (top Node) {
+ i := len(*s)
+ for i > 0 && (*s)[i-1].End() <= pos {
+ top = (*s)[i-1]
+ i--
+ }
+ *s = (*s)[0:i]
+ return top
+}
+
+// NewCommentMap creates a new comment map by associating comment groups
+// of the comments list with the nodes of the AST specified by node.
+//
+// A comment group g is associated with a node n if:
+//
+// - g starts on the same line as n ends
+// - g starts on the line immediately following n, and there is
+// at least one empty line after g and before the next node
+// - g starts before n and is not associated to the node before n
+// via the previous rules
+//
+// NewCommentMap tries to associate a comment group to the "largest"
+// node possible: For instance, if the comment is a line comment
+// trailing an assignment, the comment is associated with the entire
+// assignment rather than just the last operand in the assignment.
+//
+func NewCommentMap(fset *token.FileSet, node Node, comments []*CommentGroup) CommentMap {
+ if len(comments) == 0 {
+ return nil // no comments to map
+ }
+
+ cmap := make(CommentMap)
+
+ // set up comment reader r
+ tmp := make([]*CommentGroup, len(comments))
+ copy(tmp, comments) // don't change incomming comments
+ sortComments(tmp)
+ r := commentListReader{fset: fset, list: tmp} // !r.eol() because len(comments) > 0
+ r.next()
+
+ // create node list in lexical order
+ nodes := nodeList(node)
+ nodes = append(nodes, nil) // append sentinel
+
+ // set up iteration variables
+ var (
+ p Node // previous node
+ pend token.Position // end of p
+ pg Node // previous node group (enclosing nodes of "importance")
+ pgend token.Position // end of pg
+ stack nodeStack // stack of node groups
+ )
+
+ for _, q := range nodes {
+ var qpos token.Position
+ if q != nil {
+ qpos = fset.Position(q.Pos()) // current node position
+ } else {
+ // set fake sentinel position to infinity so that
+ // all comments get processed before the sentinel
+ const infinity = 1 << 30
+ qpos.Offset = infinity
+ qpos.Line = infinity
+ }
+
+ // process comments before current node
+ for r.end.Offset <= qpos.Offset {
+ // determine recent node group
+ if top := stack.pop(r.comment.Pos()); top != nil {
+ pg = top
+ pgend = fset.Position(pg.End())
+ }
+ // Try to associate a comment first with a node group
+ // (i.e., a node of "importance" such as a declaration);
+ // if that fails, try to associate it with the most recent
+ // node.
+ // TODO(gri) try to simplify the logic below
+ var assoc Node
+ switch {
+ case pg != nil &&
+ (pgend.Line == r.pos.Line ||
+ pgend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line):
+ // 1) comment starts on same line as previous node group ends, or
+ // 2) comment starts on the line immediately after the
+ // previous node group and there is an empty line before
+ // the current node
+ // => associate comment with previous node group
+ assoc = pg
+ case p != nil &&
+ (pend.Line == r.pos.Line ||
+ pend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line ||
+ q == nil):
+ // same rules apply as above for p rather than pg,
+ // but also associate with p if we are at the end (q == nil)
+ assoc = p
+ default:
+ // otherwise, associate comment with current node
+ if q == nil {
+ // we can only reach here if there was no p
+ // which would imply that there were no nodes
+ panic("internal error: no comments should be associated with sentinel")
+ }
+ assoc = q
+ }
+ cmap.addComment(assoc, r.comment)
+ if r.eol() {
+ return cmap
+ }
+ r.next()
+ }
+
+ // update previous node
+ p = q
+ pend = fset.Position(p.End())
+
+ // update previous node group if we see an "important" node
+ switch q.(type) {
+ case *File, *Field, Decl, Spec, Stmt:
+ stack.push(q)
+ }
+ }
+
+ return cmap
+}
+
+// Update replaces an old node in the comment map with the new node
+// and returns the new node. Comments that were associated with the
+// old node are associated with the new node.
+//
+func (cmap CommentMap) Update(old, new Node) Node {
+ if list := cmap[old]; len(list) > 0 {
+ delete(cmap, old)
+ cmap[new] = append(cmap[new], list...)
+ }
+ return new
+}
+
+// Filter returns a new comment map consisting of only those
+// entries of cmap for which a corresponding node exists in
+// the AST specified by node.
+//
+func (cmap CommentMap) Filter(node Node) CommentMap {
+ umap := make(CommentMap)
+ Inspect(node, func(n Node) bool {
+ if g := cmap[n]; len(g) > 0 {
+ umap[n] = g
+ }
+ return true
+ })
+ return umap
+}
+
+// Comments returns the list of comment groups in the comment map.
+// The result is sorted is source order.
+//
+func (cmap CommentMap) Comments() []*CommentGroup {
+ list := make([]*CommentGroup, 0, len(cmap))
+ for _, e := range cmap {
+ list = append(list, e...)
+ }
+ sortComments(list)
+ return list
+}
+
+func summary(list []*CommentGroup) string {
+ const maxLen = 40
+ var buf bytes.Buffer
+
+ // collect comments text
+loop:
+ for _, group := range list {
+ // Note: CommentGroup.Text() does too much work for what we
+ // need and would only replace this innermost loop.
+ // Just do it explicitly.
+ for _, comment := range group.List {
+ if buf.Len() >= maxLen {
+ break loop
+ }
+ buf.WriteString(comment.Text)
+ }
+ }
+
+ // truncate if too long
+ if buf.Len() > maxLen {
+ buf.Truncate(maxLen - 3)
+ buf.WriteString("...")
+ }
+
+ // replace any invisibles with blanks
+ bytes := buf.Bytes()
+ for i, b := range bytes {
+ switch b {
+ case '\t', '\n', '\r':
+ bytes[i] = ' '
+ }
+ }
+
+ return string(bytes)
+}
+
+func (cmap CommentMap) String() string {
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, "CommentMap {")
+ for node, comment := range cmap {
+ // print name of identifiers; print node type for other nodes
+ var s string
+ if ident, ok := node.(*Ident); ok {
+ s = ident.Name
+ } else {
+ s = fmt.Sprintf("%T", node)
+ }
+ fmt.Fprintf(&buf, "\t%p %20s: %s\n", node, s, summary(comment))
+ }
+ fmt.Fprintln(&buf, "}")
+ return buf.String()
+}
Oops, something went wrong.

0 comments on commit 36921a0

Please sign in to comment.