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