/
diff.go
117 lines (100 loc) · 3.01 KB
/
diff.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package gompatible
import (
"github.com/motemen/gompatible/internal/util"
)
// ObjectCategory is the category of API.
type ObjectCategory string
const (
ObjectCategoryFunc ObjectCategory = "func"
ObjectCategoryType ObjectCategory = "type"
ObjectCategoryValue ObjectCategory = "value"
)
// PackageChanges represent changes between two packages.
type PackageChanges struct {
Before *Package
After *Package
Changes map[ObjectCategory]map[string]Change
}
// Path is the import path of the package.
func (pc PackageChanges) Path() string {
if pc.Before != nil {
return pc.Before.TypesPkg.Path()
}
return pc.After.TypesPkg.Path()
}
// Funcs returns API changes of functions.
func (pc PackageChanges) Funcs() map[string]FuncChange {
changes := pc.Changes[ObjectCategoryFunc]
m := make(map[string]FuncChange, len(changes))
for k, c := range changes {
m[k] = c.(FuncChange)
}
return m
}
// Types returns API changes of types.
func (pc PackageChanges) Types() map[string]TypeChange {
changes := pc.Changes[ObjectCategoryType]
m := make(map[string]TypeChange, len(changes))
for k, c := range changes {
m[k] = c.(TypeChange)
}
return m
}
// Types returns API changes of values eg. consts and vars.
func (pc PackageChanges) Values() map[string]ValueChange {
changes := pc.Changes[ObjectCategoryValue]
m := make(map[string]ValueChange, len(changes))
for k, c := range changes {
m[k] = c.(ValueChange)
}
return m
}
// DiffPackages takes two packages to produce the changes between them.
func DiffPackages(pkg1, pkg2 *Package) PackageChanges {
diff := PackageChanges{
Before: pkg1,
After: pkg2,
Changes: map[ObjectCategory]map[string]Change{
ObjectCategoryFunc: {},
ObjectCategoryType: {},
ObjectCategoryValue: {},
},
}
for _, name := range util.SortedStringSet(util.MapKeys(pkg1.Funcs), util.MapKeys(pkg2.Funcs)) {
Debugf("%q", name)
diff.Changes[ObjectCategoryFunc][name] = FuncChange{
Before: pkg1.Funcs[name],
After: pkg2.Funcs[name],
}
}
for _, name := range util.SortedStringSet(util.MapKeys(pkg1.Types), util.MapKeys(pkg2.Types)) {
type1 := pkg1.Types[name]
type2 := pkg2.Types[name]
diff.Changes[ObjectCategoryType][name] = TypeChange{
Before: pkg1.Types[name],
After: pkg2.Types[name],
}
if type1 != nil && type2 != nil {
for _, fname := range util.SortedStringSet(util.MapKeys(type1.Funcs), util.MapKeys(type2.Funcs)) {
diff.Changes[ObjectCategoryFunc][fname] = FuncChange{
Before: type1.Funcs[fname],
After: type2.Funcs[fname],
}
}
for _, mname := range util.SortedStringSet(util.MapKeys(type1.Methods), util.MapKeys(type2.Methods)) {
diff.Changes[ObjectCategoryFunc][name+"."+mname] = FuncChange{
Before: type1.Methods[mname],
After: type2.Methods[mname],
}
}
}
}
for _, name := range util.SortedStringSet(util.MapKeys(pkg1.Values), util.MapKeys(pkg2.Values)) {
Debugf("%q", name)
diff.Changes[ObjectCategoryValue][name] = ValueChange{
Before: pkg1.Values[name],
After: pkg2.Values[name],
}
}
return diff
}