Commit 21805061 authored by Robert Griesemer's avatar Robert Griesemer

godoc: internal cleanup: remove a TODO

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8005044
parent 3660b532
...@@ -23,15 +23,21 @@ import ( ...@@ -23,15 +23,21 @@ import (
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Implementation of FormatSelections // Implementation of FormatSelections
// A Selection is a function returning offset pairs []int{a, b} // A Segment describes a text segment [start, end).
// describing consecutive non-overlapping text segments [a, b). // The zero value of a Segment is a ready-to-use empty segment.
// If there are no more segments, a Selection must return nil.
// //
// TODO It's more efficient to return a pair (a, b int) instead type Segment struct {
// of creating lots of slices. Need to determine how to start, end int
// indicate the end of a Selection. }
func (seg *Segment) isEmpty() bool { return seg.start >= seg.end }
// A Selection is an "iterator" function returning a text segment.
// Repeated calls to a selection return consecutive, non-overlapping,
// non-empty segments, followed by an infinite sequence of empty
// segments. The first empty segment marks the end of the selection.
// //
type Selection func() []int type Selection func() Segment
// A LinkWriter writes some start or end "tag" to w for the text offset offs. // A LinkWriter writes some start or end "tag" to w for the text offset offs.
// It is called by FormatSelections at the start or end of each link segment. // It is called by FormatSelections at the start or end of each link segment.
...@@ -141,17 +147,17 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection, ...@@ -141,17 +147,17 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
// //
type merger struct { type merger struct {
selections []Selection selections []Selection
segments [][]int // segments[i] is the next segment of selections[i] segments []Segment // segments[i] is the next segment of selections[i]
} }
const infinity int = 2e9 const infinity int = 2e9
func newMerger(selections []Selection) *merger { func newMerger(selections []Selection) *merger {
segments := make([][]int, len(selections)) segments := make([]Segment, len(selections))
for i, sel := range selections { for i, sel := range selections {
segments[i] = []int{infinity, infinity} segments[i] = Segment{infinity, infinity}
if sel != nil { if sel != nil {
if seg := sel(); seg != nil { if seg := sel(); !seg.isEmpty() {
segments[i] = seg segments[i] = seg
} }
} }
...@@ -170,12 +176,12 @@ func (m *merger) next() (index, offs int, start bool) { ...@@ -170,12 +176,12 @@ func (m *merger) next() (index, offs int, start bool) {
index = -1 index = -1
for i, seg := range m.segments { for i, seg := range m.segments {
switch { switch {
case seg[0] < offs: case seg.start < offs:
offs = seg[0] offs = seg.start
index = i index = i
start = true start = true
case seg[1] < offs: case seg.end < offs:
offs = seg[1] offs = seg.end
index = i index = i
start = false start = false
} }
...@@ -188,18 +194,17 @@ func (m *merger) next() (index, offs int, start bool) { ...@@ -188,18 +194,17 @@ func (m *merger) next() (index, offs int, start bool) {
// either way it is ok to consume the start offset: set it // either way it is ok to consume the start offset: set it
// to infinity so it won't be considered in the following // to infinity so it won't be considered in the following
// next call // next call
m.segments[index][0] = infinity m.segments[index].start = infinity
if start { if start {
return return
} }
// end offset found - consume it // end offset found - consume it
m.segments[index][1] = infinity m.segments[index].end = infinity
// advance to the next segment for that selection // advance to the next segment for that selection
seg := m.selections[index]() seg := m.selections[index]()
if seg == nil { if !seg.isEmpty() {
return m.segments[index] = seg
} }
m.segments[index] = seg
return return
} }
...@@ -209,7 +214,7 @@ func (m *merger) next() (index, offs int, start bool) { ...@@ -209,7 +214,7 @@ func (m *merger) next() (index, offs int, start bool) {
// lineSelection returns the line segments for text as a Selection. // lineSelection returns the line segments for text as a Selection.
func lineSelection(text []byte) Selection { func lineSelection(text []byte) Selection {
i, j := 0, 0 i, j := 0, 0
return func() (seg []int) { return func() (seg Segment) {
// find next newline, if any // find next newline, if any
for j < len(text) { for j < len(text) {
j++ j++
...@@ -219,7 +224,7 @@ func lineSelection(text []byte) Selection { ...@@ -219,7 +224,7 @@ func lineSelection(text []byte) Selection {
} }
if i < j { if i < j {
// text[i:j] constitutes a line // text[i:j] constitutes a line
seg = []int{i, j} seg = Segment{i, j}
i = j i = j
} }
return return
...@@ -234,7 +239,7 @@ func tokenSelection(src []byte, sel token.Token) Selection { ...@@ -234,7 +239,7 @@ func tokenSelection(src []byte, sel token.Token) Selection {
fset := token.NewFileSet() fset := token.NewFileSet()
file := fset.AddFile("", fset.Base(), len(src)) file := fset.AddFile("", fset.Base(), len(src))
s.Init(file, src, nil, scanner.ScanComments) s.Init(file, src, nil, scanner.ScanComments)
return func() (seg []int) { return func() (seg Segment) {
for { for {
pos, tok, lit := s.Scan() pos, tok, lit := s.Scan()
if tok == token.EOF { if tok == token.EOF {
...@@ -242,7 +247,7 @@ func tokenSelection(src []byte, sel token.Token) Selection { ...@@ -242,7 +247,7 @@ func tokenSelection(src []byte, sel token.Token) Selection {
} }
offs := file.Offset(pos) offs := file.Offset(pos)
if tok == sel { if tok == sel {
seg = []int{offs, offs + len(lit)} seg = Segment{offs, offs + len(lit)}
break break
} }
} }
...@@ -251,13 +256,20 @@ func tokenSelection(src []byte, sel token.Token) Selection { ...@@ -251,13 +256,20 @@ func tokenSelection(src []byte, sel token.Token) Selection {
} }
// makeSelection is a helper function to make a Selection from a slice of pairs. // makeSelection is a helper function to make a Selection from a slice of pairs.
// Pairs describing empty segments are ignored.
//
func makeSelection(matches [][]int) Selection { func makeSelection(matches [][]int) Selection {
return func() (seg []int) { i := 0
if len(matches) > 0 { return func() Segment {
seg = matches[0] for i < len(matches) {
matches = matches[1:] m := matches[i]
i++
if m[0] < m[1] {
// non-empty segment
return Segment{m[0], m[1]}
}
} }
return return Segment{}
} }
} }
......
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