github.com/v2fly/tools@v0.100.0/godoc/corpus.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package godoc 6 7 import ( 8 "errors" 9 "sync" 10 "time" 11 12 "github.com/v2fly/tools/godoc/analysis" 13 "github.com/v2fly/tools/godoc/util" 14 "github.com/v2fly/tools/godoc/vfs" 15 ) 16 17 // A Corpus holds all the state related to serving and indexing a 18 // collection of Go code. 19 // 20 // Construct a new Corpus with NewCorpus, then modify options, 21 // then call its Init method. 22 type Corpus struct { 23 fs vfs.FileSystem 24 25 // Verbose logging. 26 Verbose bool 27 28 // IndexEnabled controls whether indexing is enabled. 29 IndexEnabled bool 30 31 // IndexFiles specifies a glob pattern specifying index files. 32 // If not empty, the index is read from these files in sorted 33 // order. 34 IndexFiles string 35 36 // IndexThrottle specifies the indexing throttle value 37 // between 0.0 and 1.0. At 0.0, the indexer always sleeps. 38 // At 1.0, the indexer never sleeps. Because 0.0 is useless 39 // and redundant with setting IndexEnabled to false, the 40 // zero value for IndexThrottle means 0.9. 41 IndexThrottle float64 42 43 // IndexInterval specifies the time to sleep between reindexing 44 // all the sources. 45 // If zero, a default is used. If negative, the index is only 46 // built once. 47 IndexInterval time.Duration 48 49 // IndexDocs enables indexing of Go documentation. 50 // This will produce search results for exported types, functions, 51 // methods, variables, and constants, and will link to the godoc 52 // documentation for those identifiers. 53 IndexDocs bool 54 55 // IndexGoCode enables indexing of Go source code. 56 // This will produce search results for internal and external identifiers 57 // and will link to both declarations and uses of those identifiers in 58 // source code. 59 IndexGoCode bool 60 61 // IndexFullText enables full-text indexing. 62 // This will provide search results for any matching text in any file that 63 // is indexed, including non-Go files (see whitelisted in index.go). 64 // Regexp searching is supported via full-text indexing. 65 IndexFullText bool 66 67 // MaxResults optionally specifies the maximum results for indexing. 68 MaxResults int 69 70 // SummarizePackage optionally specifies a function to 71 // summarize a package. It exists as an optimization to 72 // avoid reading files to parse package comments. 73 // 74 // If SummarizePackage returns false for ok, the caller 75 // ignores all return values and parses the files in the package 76 // as if SummarizePackage were nil. 77 // 78 // If showList is false, the package is hidden from the 79 // package listing. 80 SummarizePackage func(pkg string) (summary string, showList, ok bool) 81 82 // IndexDirectory optionally specifies a function to determine 83 // whether the provided directory should be indexed. The dir 84 // will be of the form "/src/cmd/6a", "/doc/play", 85 // "/src/io", etc. 86 // If nil, all directories are indexed if indexing is enabled. 87 IndexDirectory func(dir string) bool 88 89 // Send a value on this channel to trigger a metadata refresh. 90 // It is buffered so that if a signal is not lost if sent 91 // during a refresh. 92 refreshMetadataSignal chan bool 93 94 // file system information 95 fsTree util.RWValue // *Directory tree of packages, updated with each sync (but sync code is removed now) 96 fsModified util.RWValue // timestamp of last call to invalidateIndex 97 docMetadata util.RWValue // mapping from paths to *Metadata 98 99 // SearchIndex is the search index in use. 100 searchIndex util.RWValue 101 102 // Analysis is the result of type and pointer analysis. 103 Analysis analysis.Result 104 105 // flag to check whether a corpus is initialized or not 106 initMu sync.RWMutex 107 initDone bool 108 109 // pkgAPIInfo contains the information about which package API 110 // features were added in which version of Go. 111 pkgAPIInfo apiVersions 112 } 113 114 // NewCorpus returns a new Corpus from a filesystem. 115 // The returned corpus has all indexing enabled and MaxResults set to 1000. 116 // Change or set any options on Corpus before calling the Corpus.Init method. 117 func NewCorpus(fs vfs.FileSystem) *Corpus { 118 c := &Corpus{ 119 fs: fs, 120 refreshMetadataSignal: make(chan bool, 1), 121 122 MaxResults: 1000, 123 IndexEnabled: true, 124 IndexDocs: true, 125 IndexGoCode: true, 126 IndexFullText: true, 127 } 128 return c 129 } 130 131 func (c *Corpus) CurrentIndex() (*Index, time.Time) { 132 v, t := c.searchIndex.Get() 133 idx, _ := v.(*Index) 134 return idx, t 135 } 136 137 func (c *Corpus) FSModifiedTime() time.Time { 138 _, ts := c.fsModified.Get() 139 return ts 140 } 141 142 // Init initializes Corpus, once options on Corpus are set. 143 // It must be called before any subsequent method calls. 144 func (c *Corpus) Init() error { 145 if err := c.initFSTree(); err != nil { 146 return err 147 } 148 c.updateMetadata() 149 go c.refreshMetadataLoop() 150 151 c.initMu.Lock() 152 c.initDone = true 153 c.initMu.Unlock() 154 return nil 155 } 156 157 func (c *Corpus) initFSTree() error { 158 dir := c.newDirectory("/", -1) 159 if dir == nil { 160 return errors.New("godoc: corpus fstree is nil") 161 } 162 c.fsTree.Set(dir) 163 c.invalidateIndex() 164 return nil 165 }