Skip to content

Commit 45227b6

Browse files
committed
internal/modindex: add LookupAll(pkg, names)
The new function LookupAll returns a map from import paths to []Candidate, where the []Candidate contains all the names. This improves the current situation where the caller of Lookup() has to figure out if all the missing names have been found. Also, the parallelism while building a new index is now limited to half the number of cpus. Change-Id: I7c5543ed8675d49f630775adea204090c201930c Reviewed-on: https://go-review.googlesource.com/c/tools/+/643495 Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 71c7ff3 commit 45227b6

File tree

3 files changed

+98
-4
lines changed

3 files changed

+98
-4
lines changed

internal/modindex/lookup.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,36 @@ const (
3535
Func
3636
)
3737

38+
// LookupAll only returns those Candidates whose import path
39+
// finds all the nms.
40+
func (ix *Index) LookupAll(pkg string, names ...string) map[string][]Candidate {
41+
// this can be made faster when benchmarks show that it needs to be
42+
names = uniquify(names)
43+
byImpPath := make(map[string][]Candidate)
44+
for _, nm := range names {
45+
cands := ix.Lookup(pkg, nm, false)
46+
for _, c := range cands {
47+
byImpPath[c.ImportPath] = append(byImpPath[c.ImportPath], c)
48+
}
49+
}
50+
for k, v := range byImpPath {
51+
if len(v) != len(names) {
52+
delete(byImpPath, k)
53+
}
54+
}
55+
return byImpPath
56+
}
57+
58+
// remove duplicates
59+
func uniquify(in []string) []string {
60+
if len(in) == 0 {
61+
return in
62+
}
63+
in = slices.Clone(in)
64+
slices.Sort(in)
65+
return slices.Compact(in)
66+
}
67+
3868
// Lookup finds all the symbols in the index with the given PkgName and name.
3969
// If prefix is true, it finds all of these with name as a prefix.
4070
func (ix *Index) Lookup(pkg, name string, prefix bool) []Candidate {

internal/modindex/lookup_test.go

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ func okresult(r result, p Candidate) bool {
6868
}
6969

7070
func TestLookup(t *testing.T) {
71-
log.SetFlags(log.Lshortfile)
7271
dir := testModCache(t)
7372
wrtData(t, dir, thedata)
7473
if _, err := indexModCache(dir, true); err != nil {
@@ -133,3 +132,67 @@ func wrtData(t *testing.T, dir string, data tdata) {
133132
fd.WriteString(item.code + "\n")
134133
}
135134
}
135+
136+
func TestLookupAll(t *testing.T) {
137+
log.SetFlags(log.Lshortfile)
138+
dir := testModCache(t)
139+
wrtModule := func(mod string, nms ...string) {
140+
dname := filepath.Join(dir, mod)
141+
if err := os.MkdirAll(dname, 0755); err != nil {
142+
t.Fatal(err)
143+
}
144+
fname := filepath.Join(dname, "foo.go")
145+
fd, err := os.Create(fname)
146+
if err != nil {
147+
t.Fatal(err)
148+
}
149+
defer fd.Close()
150+
if _, err := fd.WriteString(fmt.Sprintf("package foo\n")); err != nil {
151+
t.Fatal(err)
152+
}
153+
for _, nm := range nms {
154+
fd.WriteString(fmt.Sprintf("func %s() {}\n", nm))
155+
}
156+
}
157+
wrtModule("a.com/go/[email protected]", "A", "B", "C", "D")
158+
wrtModule("b.com/go/[email protected]", "A", "B", "C")
159+
wrtModule("c.com/go/[email protected]", "A", "B", "C", "D", "E")
160+
161+
if _, err := indexModCache(dir, true); err != nil {
162+
t.Fatal(err)
163+
}
164+
ix, err := ReadIndex(dir)
165+
if err != nil {
166+
t.Fatal(err)
167+
}
168+
cands := ix.Lookup("foo", "A", false)
169+
if len(cands) != 3 {
170+
t.Errorf("got %d candidates for A, expected 3", len(cands))
171+
}
172+
got := ix.LookupAll("foo", "A", "B", "C", "D")
173+
if len(got) != 2 {
174+
t.Errorf("got %d candidates for A,B,C,D, expected 2", len(got))
175+
}
176+
got = ix.LookupAll("foo", []string{"A", "B", "C", "D", "E"}...)
177+
if len(got) != 1 {
178+
t.Errorf("got %d candidates for A,B,C,D,E, expected 1", len(got))
179+
}
180+
}
181+
182+
func TestUniquify(t *testing.T) {
183+
var v []string
184+
for i := 1; i < 4; i++ {
185+
v = append(v, "A")
186+
w := uniquify(v)
187+
if len(w) != 1 {
188+
t.Errorf("got %d, expected 1", len(w))
189+
}
190+
}
191+
for i := 1; i < 3; i++ {
192+
v = append(v, "B", "C")
193+
w := uniquify(v)
194+
if len(w) != 3 {
195+
t.Errorf("got %d, expected 3", len(w))
196+
}
197+
}
198+
}

internal/modindex/symbols.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"go/types"
1313
"os"
1414
"path/filepath"
15+
"runtime"
1516
"slices"
1617
"strings"
1718

@@ -29,14 +30,14 @@ import (
2930
type symbol struct {
3031
pkg string // name of the symbols's package
3132
name string // declared name
32-
kind string // T, C, V, or F
33+
kind string // T, C, V, or F, follwed by D if deprecated
3334
sig string // signature information, for F
3435
}
3536

3637
// find the symbols for the best directories
3738
func getSymbols(cd Abspath, dirs map[string][]*directory) {
3839
var g errgroup.Group
39-
g.SetLimit(-1) // maybe throttle this some day
40+
g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
4041
for _, vv := range dirs {
4142
// throttling some day?
4243
d := vv[0]
@@ -111,7 +112,7 @@ func getFileExports(f *ast.File) []symbol {
111112
// print struct tags. So for this to happen the type of a formal parameter
112113
// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
113114
// would have to show the struct tag. Even testing for this case seems
114-
// a waste of effort, but let's not ignore such pathologies
115+
// a waste of effort, but let's remember the possibility
115116
if strings.Contains(tp, "$") {
116117
continue
117118
}

0 commit comments

Comments
 (0)