Skip to content

Commit 0b61e23

Browse files
committed
Move DependencyMap to spaghetti-analyzer
1 parent ea9c188 commit 0b61e23

File tree

3 files changed

+1
-368
lines changed

3 files changed

+1
-368
lines changed

data/data.go

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package data
33
import (
44
"fmt"
55
"regexp"
6-
"sort"
7-
"strings"
86
)
97

108
// PkgType can be one of: Standard, Tool, DB or God
@@ -21,12 +19,6 @@ const (
2119
var typeLetters = []rune("STDG")
2220
var typeFormats = []string{"", "_", "`", "**"}
2321

24-
// PkgImports contains the package type and the imported internal packages with their types.
25-
type PkgImports struct {
26-
PkgType PkgType
27-
Imports map[string]PkgType
28-
}
29-
3022
// TypeLetter returns the type letter associated with package type t ('S', 'T',
3123
// 'D' or 'G').
3224
func TypeLetter(t PkgType) rune {
@@ -57,73 +49,6 @@ type Pattern struct {
5749
DollarIdxs []int
5850
}
5951

60-
// DependencyMap is mapping importing package to imported packages.
61-
// importingPackageName -> (importedPackageNames -> PkgType)
62-
// An imported package name could be added multiple times to the same importing
63-
// package name due to test packages.
64-
type DependencyMap map[string]PkgImports
65-
66-
// SortedPkgNames returns the sorted keys (package names) of the dependency map.
67-
func (dm DependencyMap) SortedPkgNames() []string {
68-
names := make([]string, 0, len(dm))
69-
for pkg := range dm {
70-
names = append(names, pkg)
71-
}
72-
sort.Strings(names)
73-
return names
74-
}
75-
76-
// FilterDepMap filters allMap to contain only packages matching idx and its transitive
77-
// dependencies. Entries matching other indices in links are filtered, too.
78-
func FilterDepMap(allMap DependencyMap, idx int, links PatternList) DependencyMap {
79-
if idx < 0 || len(links) == 0 {
80-
return allMap
81-
}
82-
83-
fltrMap := make(DependencyMap, len(allMap))
84-
for pkg := range allMap {
85-
if i := DocMatchStringIndex(pkg, links); i >= 0 && i == idx {
86-
copyDepsRecursive(allMap, pkg, fltrMap, links, idx)
87-
}
88-
}
89-
return fltrMap
90-
}
91-
func copyDepsRecursive(
92-
allMap DependencyMap,
93-
startPkg string,
94-
fltrMap DependencyMap,
95-
links PatternList,
96-
idx int,
97-
) {
98-
if i := DocMatchStringIndex(startPkg, links); i >= 0 && i != idx {
99-
return
100-
}
101-
imps, ok := allMap[startPkg]
102-
if !ok {
103-
return
104-
}
105-
fltrMap[startPkg] = imps
106-
for pkg := range imps.Imports {
107-
copyDepsRecursive(allMap, pkg, fltrMap, links, idx)
108-
}
109-
}
110-
111-
// PkgForPattern returns the (parent) package of the given package pattern.
112-
// If pkg doesn't contain any wildcard '*' the whole string is returned.
113-
// Otherwise everything up to the last '/' before the wildcard or
114-
// the empty string if there is no '/' before it.
115-
func PkgForPattern(pkg string) string {
116-
i := strings.IndexRune(pkg, '*')
117-
if i < 0 {
118-
return pkg
119-
}
120-
i = strings.LastIndex(pkg[:i], "/")
121-
if i > 0 {
122-
return pkg[:i]
123-
}
124-
return ""
125-
}
126-
12752
// RegexpForPattern converts the given pattern including wildcards and variables
12853
// into a proper regular expression that can be used for matching.
12954
func RegexpForPattern(pattern string, allowDollar EnumDollar, maxDollar int,

data/data_test.go

Lines changed: 0 additions & 265 deletions
Original file line numberDiff line numberDiff line change
@@ -2,276 +2,11 @@ package data_test
22

33
import (
44
"reflect"
5-
"sort"
6-
"strings"
75
"testing"
86

97
"github.com/flowdev/spaghetti-cutter/data"
108
)
119

12-
func TestDependencyMapSortedPkgNames(t *testing.T) {
13-
givenDepMap := map[string]data.PkgImports{
14-
"b": data.PkgImports{},
15-
"a": data.PkgImports{},
16-
"aa": data.PkgImports{},
17-
"b ": data.PkgImports{},
18-
"a ": data.PkgImports{},
19-
}
20-
expectedNames := []string{"a", "a ", "aa", "b", "b "}
21-
22-
actualNames := data.DependencyMap(givenDepMap).SortedPkgNames()
23-
if len(actualNames) != len(givenDepMap) {
24-
t.Errorf("expected %d names, actual %d",
25-
len(givenDepMap), len(actualNames))
26-
}
27-
if !reflect.DeepEqual(actualNames, expectedNames) {
28-
t.Errorf("expected names to be %q, got %q", expectedNames, actualNames)
29-
}
30-
}
31-
32-
func TestFilterDepMap(t *testing.T) {
33-
manyLinks, err := data.NewSimplePatternList([]string{"a", "b/c/d", "e**", "f/**"}, "test")
34-
if err != nil {
35-
t.Fatalf("got unexpected error: %v", err)
36-
}
37-
bigDepMap := data.DependencyMap{
38-
"a": data.PkgImports{
39-
PkgType: data.TypeGod,
40-
Imports: map[string]data.PkgType{
41-
"b/c/d": data.TypeTool,
42-
"epsilon": data.TypeTool,
43-
"escher": data.TypeTool,
44-
"z": data.TypeDB,
45-
"f": data.TypeStandard,
46-
},
47-
},
48-
"z": data.PkgImports{
49-
PkgType: data.TypeDB,
50-
Imports: map[string]data.PkgType{
51-
"b/c/d": data.TypeTool,
52-
"epsilon": data.TypeTool,
53-
"escher": data.TypeTool,
54-
"x": data.TypeDB,
55-
},
56-
},
57-
"x": data.PkgImports{
58-
PkgType: data.TypeDB,
59-
Imports: map[string]data.PkgType{
60-
"b/c/d": data.TypeTool,
61-
"escher": data.TypeTool,
62-
},
63-
},
64-
"m": data.PkgImports{
65-
PkgType: data.TypeStandard,
66-
Imports: map[string]data.PkgType{
67-
"b/c/d": data.TypeTool,
68-
"x": data.TypeDB,
69-
},
70-
},
71-
"f": data.PkgImports{
72-
PkgType: data.TypeStandard,
73-
Imports: map[string]data.PkgType{
74-
"f/g": data.TypeStandard,
75-
"f/h": data.TypeStandard,
76-
"f/i": data.TypeStandard,
77-
},
78-
},
79-
"f/g": data.PkgImports{
80-
PkgType: data.TypeStandard,
81-
Imports: map[string]data.PkgType{
82-
"f/j": data.TypeStandard,
83-
"escher": data.TypeTool,
84-
"x": data.TypeDB,
85-
},
86-
},
87-
"f/h": data.PkgImports{
88-
PkgType: data.TypeStandard,
89-
Imports: map[string]data.PkgType{
90-
"x": data.TypeDB,
91-
"m": data.TypeStandard,
92-
},
93-
},
94-
"f/i": data.PkgImports{
95-
PkgType: data.TypeStandard,
96-
Imports: map[string]data.PkgType{
97-
"escher": data.TypeTool,
98-
},
99-
},
100-
}
101-
t.Logf("bigDepMap:\n%s", prettyPrint(bigDepMap))
102-
103-
specs := []struct {
104-
name string
105-
givenIdx int
106-
givenLinks data.PatternList
107-
expectedDepMap string
108-
}{
109-
{
110-
name: "negative-index",
111-
givenIdx: -123,
112-
givenLinks: manyLinks,
113-
expectedDepMap: prettyPrint(bigDepMap),
114-
}, {
115-
name: "no-links",
116-
givenIdx: 0,
117-
givenLinks: data.PatternList{},
118-
expectedDepMap: prettyPrint(bigDepMap),
119-
}, {
120-
name: "no-wildcard-leave-package",
121-
givenIdx: 1,
122-
givenLinks: manyLinks,
123-
expectedDepMap: ``,
124-
}, {
125-
name: "no-wildcard-tree",
126-
givenIdx: 0,
127-
givenLinks: manyLinks,
128-
expectedDepMap: `a [G] imports: b/c/d [T]
129-
a [G] imports: epsilon [T]
130-
a [G] imports: escher [T]
131-
a [G] imports: f [S]
132-
a [G] imports: z [D]
133-
x [D] imports: b/c/d [T]
134-
x [D] imports: escher [T]
135-
z [D] imports: b/c/d [T]
136-
z [D] imports: epsilon [T]
137-
z [D] imports: escher [T]
138-
z [D] imports: x [D]`,
139-
}, {
140-
name: "wildcard-leave-packages",
141-
givenIdx: 2,
142-
givenLinks: manyLinks,
143-
expectedDepMap: ``,
144-
}, {
145-
name: "wildcard-tree",
146-
givenIdx: 3,
147-
givenLinks: manyLinks,
148-
expectedDepMap: `f [S] imports: f/g [S]
149-
f [S] imports: f/h [S]
150-
f [S] imports: f/i [S]
151-
f/g [S] imports: escher [T]
152-
f/g [S] imports: f/j [S]
153-
f/g [S] imports: x [D]
154-
f/h [S] imports: m [S]
155-
f/h [S] imports: x [D]
156-
f/i [S] imports: escher [T]
157-
m [S] imports: b/c/d [T]
158-
m [S] imports: x [D]
159-
x [D] imports: b/c/d [T]
160-
x [D] imports: escher [T]`,
161-
},
162-
}
163-
164-
for _, spec := range specs {
165-
t.Run(spec.name, func(t *testing.T) {
166-
actualDepMap := data.FilterDepMap(bigDepMap, spec.givenIdx, spec.givenLinks)
167-
sDeps := prettyPrint(actualDepMap)
168-
if sDeps != spec.expectedDepMap {
169-
failWithDiff(t, spec.expectedDepMap, sDeps)
170-
}
171-
})
172-
}
173-
}
174-
func prettyPrint(deps data.DependencyMap) string {
175-
sb := strings.Builder{}
176-
177-
for _, pkg := range deps.SortedPkgNames() {
178-
imps := deps[pkg]
179-
pkgTypeRune := data.TypeLetter(imps.PkgType)
180-
181-
for _, imp := range sortedImpNames(imps.Imports) {
182-
sb.WriteString(pkg)
183-
sb.WriteString(" [")
184-
sb.WriteRune(pkgTypeRune)
185-
sb.WriteString("] imports: ")
186-
sb.WriteString(imp)
187-
sb.WriteString(" [")
188-
sb.WriteRune(data.TypeLetter(imps.Imports[imp]))
189-
sb.WriteString("]\n")
190-
}
191-
}
192-
193-
return sb.String()
194-
}
195-
func failWithDiff(t *testing.T, expected, actual string) {
196-
exps := strings.Split(expected, "\n")
197-
acts := strings.Split(actual, "\n")
198-
199-
i := 0
200-
j := 0
201-
n := len(exps) - 1
202-
m := len(acts) - 1
203-
if n >= 0 && exps[n] == "" {
204-
n--
205-
}
206-
if m >= 0 && acts[m] == "" {
207-
m--
208-
}
209-
for i <= n && j <= m {
210-
if exps[i] < acts[j] {
211-
t.Errorf("expected but missing: %s", exps[i])
212-
i++
213-
} else if exps[i] == acts[j] {
214-
i++
215-
j++
216-
} else if exps[i] > acts[j] {
217-
t.Errorf("actual but unexpected: %s", acts[j])
218-
j++
219-
}
220-
}
221-
for ; i <= n; i++ {
222-
t.Errorf("expected but missing: %s", exps[i])
223-
}
224-
for ; j <= m; j++ {
225-
t.Errorf("actual but unexpected: %s", acts[j])
226-
}
227-
}
228-
func sortedImpNames(imps map[string]data.PkgType) []string {
229-
names := make([]string, 0, len(imps))
230-
for imp := range imps {
231-
names = append(names, imp)
232-
}
233-
sort.Strings(names)
234-
return names
235-
}
236-
237-
func TestPkgForPattern(t *testing.T) {
238-
specs := []struct {
239-
name string
240-
givenPattern string
241-
expectedPkg string
242-
}{
243-
{
244-
name: "no-wildcard",
245-
givenPattern: "abc/def/ghi",
246-
expectedPkg: "abc/def/ghi",
247-
}, {
248-
name: "one-simple-wildcard",
249-
givenPattern: "abc/def/*",
250-
expectedPkg: "abc/def",
251-
}, {
252-
name: "one-middle-wildcard",
253-
givenPattern: "abc/def/gh*i",
254-
expectedPkg: "abc/def",
255-
}, {
256-
name: "many-wildcards",
257-
givenPattern: "abc/d**e*f/*",
258-
expectedPkg: "abc",
259-
}, {
260-
name: "no-slash",
261-
givenPattern: "abc*",
262-
expectedPkg: "",
263-
},
264-
}
265-
for _, spec := range specs {
266-
t.Run(spec.name, func(t *testing.T) {
267-
actualPkg := data.PkgForPattern(spec.givenPattern)
268-
if actualPkg != spec.expectedPkg {
269-
t.Errorf("expected package %q, actual %q", spec.expectedPkg, actualPkg)
270-
}
271-
})
272-
}
273-
}
274-
27510
func TestRegexpForPattern(t *testing.T) {
27611
specs := []struct {
27712
name string

0 commit comments

Comments
 (0)