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:
parent
936715c71c
commit
345b6437fc
104
godoc/index.go
104
godoc/index.go
@ -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:
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user