1
0
mirror of https://github.com/golang/go synced 2024-11-05 14:56:10 -07:00

godoc: Order package results by import count.

Allow searching for packages by directory components.

LGTM=sameer
R=sameer, bradfitz
CC=golang-codereviews
https://golang.org/cl/104220043
This commit is contained in:
Brad Garcia 2014-06-27 12:47:39 -04:00
parent 936715c71c
commit 345b6437fc
2 changed files with 103 additions and 29 deletions

View File

@ -358,25 +358,47 @@ type Ident struct {
Doc string // e.g. "NewRequest returns a new Request..."
}
type byPackage []Ident
func (s byPackage) Len() int { return len(s) }
func (s byPackage) Less(i, j int) bool {
if s[i].Package == s[j].Package {
return s[i].Path < s[j].Path
}
return s[i].Package < s[j].Package
// byImportCount sorts the given slice of Idents by the import
// counts of the packages to which they belong.
type byImportCount struct {
Idents []Ident
ImportCount map[string]int
}
func (s byPackage) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// Filter creates a new Ident list where the results match the given
func (ic byImportCount) Len() int {
return len(ic.Idents)
}
func (ic byImportCount) Less(i, j int) bool {
ri := ic.ImportCount[ic.Idents[i].Path]
rj := ic.ImportCount[ic.Idents[j].Path]
if ri == rj {
return ic.Idents[i].Path < ic.Idents[j].Path
}
return ri > rj
}
func (ic byImportCount) Swap(i, j int) {
ic.Idents[i], ic.Idents[j] = ic.Idents[j], ic.Idents[i]
}
func (ic byImportCount) String() string {
buf := bytes.NewBuffer([]byte("["))
for _, v := range ic.Idents {
buf.WriteString(fmt.Sprintf("\n\t%s, %s (%d)", v.Path, v.Name, ic.ImportCount[v.Path]))
}
buf.WriteString("\n]")
return buf.String()
}
// filter creates a new Ident list where the results match the given
// package name.
func (s byPackage) filter(pakname string) []Ident {
if s == nil {
func (ic byImportCount) filter(pakname string) []Ident {
if ic.Idents == nil {
return nil
}
var res []Ident
for _, i := range s {
for _, i := range ic.Idents {
if i.Package == pakname {
res = append(res, i)
}
@ -384,6 +406,14 @@ func (s byPackage) filter(pakname string) []Ident {
return res
}
// top returns the top n identifiers.
func (ic byImportCount) top(n int) []Ident {
if len(ic.Idents) > n {
return ic.Idents[:n]
}
return ic.Idents
}
// ----------------------------------------------------------------------------
// Indexer
@ -719,23 +749,45 @@ func (x *Indexer) indexDocs(dirname string, filename string, astFile *ast.File)
Doc: doc.Synopsis(docstr),
})
}
foundPkg := false
if x.idents[PackageClause] != nil {
pkgs := x.idents[PackageClause][docPkg.Name]
if x.idents[PackageClause] == nil {
x.idents[PackageClause] = make(map[string][]Ident)
}
// List of words under which the package identifier will be stored.
// This includes the package name and the components of the directory
// in which it resides.
words := strings.Split(pathpkg.Dir(pkgPath), "/")
if words[0] == "." {
words = []string{}
}
name := x.intern(docPkg.Name)
synopsis := doc.Synopsis(docPkg.Doc)
words = append(words, name)
pkgIdent := Ident{
Path: pkgPath,
Package: pkgName,
Name: name,
Doc: synopsis,
}
for _, word := range words {
word = x.intern(word)
found := false
pkgs := x.idents[PackageClause][word]
for i, p := range pkgs {
if p.Path == pkgPath {
foundPkg = true
if docPkg.Doc != "" {
p.Doc = doc.Synopsis(docPkg.Doc)
p.Doc = synopsis
pkgs[i] = p
}
found = true
break
}
}
if !found {
x.idents[PackageClause][word] = append(x.idents[PackageClause][word], pkgIdent)
}
}
if !foundPkg {
addIdent(PackageClause, docPkg.Name, docPkg.Doc)
}
for _, c := range docPkg.Consts {
for _, name := range c.Names {
addIdent(ConstDecl, name, c.Doc)
@ -1027,9 +1079,10 @@ func (c *Corpus) NewIndex() *Index {
suffixes = suffixarray.New(x.sources.Bytes())
}
// sort idents by the number of imports of their respective packages
for _, idMap := range x.idents {
for _, ir := range idMap {
sort.Sort(byPackage(ir))
sort.Sort(byImportCount{ir, x.importCount})
}
}
@ -1238,7 +1291,9 @@ func (x *Index) Lookup(query string) (*SearchResult, error) {
rslt.Pak = rslt.Hit.Others.filter(ident)
}
for k, v := range x.idents {
rslt.Idents[k] = v[ident]
const rsltLimit = 50
ids := byImportCount{v[ident], x.importCount}
rslt.Idents[k] = ids.top(rsltLimit)
}
case 2:
@ -1252,7 +1307,8 @@ func (x *Index) Lookup(query string) (*SearchResult, error) {
rslt.Hit = &LookupResult{decls, others}
}
for k, v := range x.idents {
rslt.Idents[k] = byPackage(v[ident]).filter(pakname)
ids := byImportCount{v[ident], x.importCount}
rslt.Idents[k] = ids.filter(pakname)
}
default:

View File

@ -234,7 +234,8 @@ func checkIdents(t *testing.T, c *Corpus, ix *Index) {
{"bar", "bar", "bar", "Package bar is another example to test races."},
{"other/bar", "bar", "bar", "Package bar is another bar package."},
},
"foo": []Ident{{"foo", "foo", "foo", "Package foo is an example."}},
"foo": []Ident{{"foo", "foo", "foo", "Package foo is an example."}},
"other": []Ident{{"other/bar", "bar", "bar", "Package bar is another bar package."}},
},
ConstDecl: map[string][]Ident{
"Pi": []Ident{{"foo", "foo", "Pi", ""}},
@ -257,6 +258,11 @@ func checkIdents(t *testing.T, c *Corpus, ix *Index) {
}
func TestIdentResultSort(t *testing.T) {
ic := map[string]int{
"/a/b/pkg1": 10,
"/a/b/pkg2": 2,
"/b/d/pkg3": 20,
}
for _, tc := range []struct {
ir []Ident
exp []Ident
@ -268,19 +274,30 @@ func TestIdentResultSort(t *testing.T) {
{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
},
exp: []Ident{
{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
},
},
{
ir: []Ident{
{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
},
exp: []Ident{
{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
},
},
} {
if sort.Sort(byPackage(tc.ir)); !reflect.DeepEqual(tc.ir, tc.exp) {
if sort.Sort(byImportCount{tc.ir, ic}); !reflect.DeepEqual(tc.ir, tc.exp) {
t.Errorf("got: %v, want %v", tc.ir, tc.exp)
}
}
}
func TestIdentPackageFilter(t *testing.T) {
func TestIdentFilter(t *testing.T) {
ic := map[string]int{}
for _, tc := range []struct {
ir []Ident
pak string
@ -298,7 +315,8 @@ func TestIdentPackageFilter(t *testing.T) {
},
},
} {
if res := byPackage(tc.ir).filter(tc.pak); !reflect.DeepEqual(res, tc.exp) {
res := byImportCount{tc.ir, ic}.filter(tc.pak)
if !reflect.DeepEqual(res, tc.exp) {
t.Errorf("got: %v, want %v", res, tc.exp)
}
}