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  }