blob: d3f9a6e5ac69fe7a9025bce26d7b9bd911939872 [file] [log] [blame]
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +10001// 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
5package godoc
6
7import (
8 "errors"
9 pathpkg "path"
Agniva De Sarker006ac432018-02-10 09:59:54 +053010 "sync"
Brad Fitzpatrick5395cfe2013-07-18 13:14:09 +100011 "time"
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +100012
Andrew Gerrand5ebbcd12014-11-10 08:50:40 +110013 "golang.org/x/tools/godoc/analysis"
14 "golang.org/x/tools/godoc/util"
15 "golang.org/x/tools/godoc/vfs"
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +100016)
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.
23type Corpus struct {
24 fs vfs.FileSystem
25
Brad Fitzpatrick705bb7f2013-07-19 10:27:53 +100026 // Verbose logging.
27 Verbose bool
28
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +100029 // 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 Fitzpatrick964f0f52013-11-05 09:35:58 -050037 // 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 Fitzpatrick4fc63232013-07-18 09:52:45 +100042 IndexThrottle float64
43
Brad Fitzpatrick42513df2013-11-06 13:31:30 -050044 // 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 Garciaf3faf8b2013-11-21 11:55:42 -050050 // 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 Fitzpatrick4fc63232013-07-18 09:52:45 +100068 // MaxResults optionally specifies the maximum results for indexing.
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +100069 MaxResults int
70
Brad Fitzpatrick766a7062013-10-30 11:34:32 -070071 // 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 Fitzpatrick964f0f52013-11-05 09:35:58 -050083 // 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 Donovan6c93dbf2014-09-10 09:02:54 -040086 // "/src/io", etc.
Brad Fitzpatrick964f0f52013-11-05 09:35:58 -050087 // If nil, all directories are indexed if indexing is enabled.
88 IndexDirectory func(dir string) bool
89
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +100090 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 Fitzpatrick5395cfe2013-07-18 13:14:09 +1000102 // SearchIndex is the search index in use.
103 searchIndex util.RWValue
Alan Donovan80c4f062014-03-14 18:58:22 -0400104
105 // Analysis is the result of type and pointer analysis.
106 Analysis analysis.Result
Agniva De Sarker006ac432018-02-10 09:59:54 +0530107
108 // flag to check whether a corpus is initialized or not
109 initMu sync.RWMutex
110 initDone bool
Devon H. O'Dell57f659e2017-12-22 17:30:39 -0800111
112 // pkgAPIInfo contains the information about which package API
113 // features were added in which version of Go.
114 pkgAPIInfo apiVersions
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +1000115}
116
117// NewCorpus returns a new Corpus from a filesystem.
Brad Garciaf3faf8b2013-11-21 11:55:42 -0500118// 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 Fitzpatrick4fc63232013-07-18 09:52:45 +1000120func NewCorpus(fs vfs.FileSystem) *Corpus {
121 c := &Corpus{
122 fs: fs,
123 refreshMetadataSignal: make(chan bool, 1),
124
Brad Garciaf3faf8b2013-11-21 11:55:42 -0500125 MaxResults: 1000,
126 IndexEnabled: true,
127 IndexDocs: true,
128 IndexGoCode: true,
129 IndexFullText: true,
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +1000130 }
131 return c
132}
133
Brad Fitzpatrick5395cfe2013-07-18 13:14:09 +1000134func (c *Corpus) CurrentIndex() (*Index, time.Time) {
135 v, t := c.searchIndex.Get()
136 idx, _ := v.(*Index)
137 return idx, t
138}
139
140func (c *Corpus) FSModifiedTime() time.Time {
141 _, ts := c.fsModified.Get()
142 return ts
143}
144
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +1000145// Init initializes Corpus, once options on Corpus are set.
146// It must be called before any subsequent method calls.
147func (c *Corpus) Init() error {
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +1000148 if err := c.initFSTree(); err != nil {
149 return err
150 }
151 c.updateMetadata()
152 go c.refreshMetadataLoop()
Agniva De Sarker006ac432018-02-10 09:59:54 +0530153
154 c.initMu.Lock()
155 c.initDone = true
156 c.initMu.Unlock()
Brad Fitzpatrick4fc63232013-07-18 09:52:45 +1000157 return nil
158}
159
160func (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}