github.com/magodo/ged@v0.0.0-20230330082724-5cc965b061e6/match.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "go/token" 6 "sort" 7 ) 8 9 type Match struct { 10 pkg string 11 ident string 12 method string 13 field string 14 } 15 16 func (m Match) String() string { 17 msg := fmt.Sprintf("%s %s", m.pkg, m.ident) 18 if m.method != "" { 19 return msg + "." + m.method + "()" 20 } 21 if m.field != "" { 22 return msg + "." + m.field 23 } 24 return msg 25 } 26 27 type MatchSlice []Match 28 29 func (ms MatchSlice) Len() int { 30 return len(ms) 31 } 32 33 func (ms MatchSlice) Less(i, j int) bool { 34 if ms[i].pkg != ms[j].pkg { 35 return ms[i].pkg < ms[j].pkg 36 } 37 if ms[i].ident != ms[j].ident { 38 return ms[i].ident < ms[j].ident 39 } 40 if ms[i].method != ms[j].method { 41 return ms[i].method < ms[j].method 42 } 43 return ms[i].field < ms[j].field 44 } 45 46 func (ms MatchSlice) Swap(i, j int) { 47 ms[i], ms[j] = ms[j], ms[i] 48 } 49 50 type Matches map[Match]Positions 51 52 func (ms Matches) Add(m Match, pos token.Position) { 53 poses, ok := ms[m] 54 if !ok { 55 poses = Positions{} 56 ms[m] = poses 57 } 58 poses[pos] = true 59 } 60 61 func (ms Matches) Merge(oms Matches) { 62 for m, poses := range oms { 63 if _, ok := ms[m]; !ok { 64 ms[m] = poses 65 continue 66 } 67 for pos := range poses { 68 ms[m][pos] = true 69 } 70 } 71 } 72 73 func (ms Matches) String() string { 74 var matchSlice MatchSlice 75 for m := range ms { 76 matchSlice = append(matchSlice, m) 77 } 78 sort.Sort(matchSlice) 79 80 var out string 81 for _, m := range matchSlice { 82 out += m.String() + ":\n" 83 for _, pos := range ms[m].Positions() { 84 out += "\t" + pos + "\n" 85 } 86 } 87 return out 88 } 89 90 type Positions map[token.Position]bool 91 92 type PositionSlice []token.Position 93 94 func (poses PositionSlice) Len() int { 95 return len(poses) 96 } 97 98 func (poses PositionSlice) Less(i, j int) bool { 99 pos1, pos2 := poses[i], poses[j] 100 if pos1.Filename != pos2.Filename { 101 return pos1.Filename < pos2.Filename 102 } 103 if pos1.Line != pos2.Line { 104 return pos1.Line < pos2.Line 105 } 106 if pos1.Column != pos2.Column { 107 return pos1.Column < pos2.Column 108 } 109 return pos1.Offset < pos2.Offset 110 } 111 112 func (poses PositionSlice) Swap(i, j int) { 113 poses[i], poses[j] = poses[j], poses[i] 114 } 115 116 func (poses Positions) Positions() []string { 117 ps := make(PositionSlice, 0, len(poses)) 118 out := make([]string, 0, len(poses)) 119 for pos := range poses { 120 ps = append(ps, pos) 121 } 122 sort.Sort(ps) 123 for _, pos := range ps { 124 out = append(out, pos.String()) 125 } 126 return out 127 }