forked from sourcegraph/sourcegraph-public-snapshot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
searcher.go
196 lines (161 loc) · 6.1 KB
/
searcher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// Package protocol contains structures used by the searcher API.
package protocol
import (
"fmt"
"strings"
"github.com/sourcegraph/sourcegraph/internal/api"
)
// Request represents a request to searcher
type Request struct {
// Repo is the name of the repository to search. eg "github.com/gorilla/mux"
Repo api.RepoName
// URL specifies the repository's Git remote URL (for gitserver). It is optional. See
// (gitserver.ExecRequest).URL for documentation on what it is used for.
URL string
// Commit is which commit to search. It is required to be resolved,
// not a ref like HEAD or master. eg
// "599cba5e7b6137d46ddf58fb1765f5d928e69604"
Commit api.CommitID
PatternInfo
// The amount of time to wait for a repo archive to fetch.
// It is parsed with time.ParseDuration.
//
// This timeout should be low when searching across many repos
// so that unfetched repos don't delay the search, and because we are likely
// to get results from the repos that have already been fetched.
//
// This timeout should be high when searching across a single repo
// because returning results slowly is better than returning no results at all.
//
// This only times out how long we wait for the fetch request;
// the fetch will still happen in the background so future requests don't have to wait.
FetchTimeout string
// The deadline for the search request.
// It is parsed with time.Time.UnmarshalText.
Deadline string
}
// PatternInfo describes a search request on a repo. Most of the fields
// are based on PatternInfo used in vscode.
type PatternInfo struct {
// Pattern is the search query. It is a regular expression if IsRegExp
// is true, otherwise a fixed string. eg "route variable"
Pattern string
// IsNegated if true will invert the matching logic for regexp searches. IsNegated=true is
// not supported for structural searches.
IsNegated bool
// IsRegExp if true will treat the Pattern as a regular expression.
IsRegExp bool
// IsStructuralPat if true will treat the pattern as a Comby structural search pattern.
IsStructuralPat bool
// IsWordMatch if true will only match the pattern at word boundaries.
IsWordMatch bool
// IsCaseSensitive if false will ignore the case of text and pattern
// when finding matches.
IsCaseSensitive bool
// ExcludePattern is a pattern that may not match the returned files' paths.
// eg '**/node_modules'
ExcludePattern string
// IncludePatterns is a list of patterns that must *all* match the returned
// files' paths.
// eg '**/node_modules'
//
// The patterns are ANDed together; a file's path must match all patterns
// for it to be kept. That is also why it is a list (unlike the singular
// ExcludePattern); it is not possible in general to construct a single
// glob or Go regexp that represents multiple such patterns ANDed together.
IncludePatterns []string
// IncludeExcludePatternAreRegExps indicates that ExcludePattern, IncludePattern,
// and IncludePatterns are regular expressions (not globs).
PathPatternsAreRegExps bool
// IncludeExcludePatternAreCaseSensitive indicates that ExcludePattern, IncludePattern,
// and IncludePatterns are case sensitive.
PathPatternsAreCaseSensitive bool
// FileMatchLimit limits the number of files with matches that are returned.
FileMatchLimit int
// PatternMatchesPath is whether the pattern should be matched against the content
// of files.
PatternMatchesContent bool
// PatternMatchesPath is whether a file whose path matches Pattern (but whose contents don't) should be
// considered a match.
PatternMatchesPath bool
// Languages is the languages passed via the lang filters (e.g., "lang:c")
Languages []string
// CombyRule is a rule that constrains matching for structural search. It only applies when IsStructuralPat is true.
CombyRule string
}
func (p *PatternInfo) String() string {
args := []string{fmt.Sprintf("%q", p.Pattern)}
if p.IsRegExp {
args = append(args, "re")
}
if p.IsStructuralPat {
if p.CombyRule != "" {
args = append(args, fmt.Sprintf("comby:%s", p.CombyRule))
} else {
args = append(args, "comby")
}
}
if p.IsWordMatch {
args = append(args, "word")
}
if p.IsCaseSensitive {
args = append(args, "case")
}
if !p.PatternMatchesContent {
args = append(args, "nocontent")
}
if !p.PatternMatchesPath {
args = append(args, "nopath")
}
if p.FileMatchLimit > 0 {
args = append(args, fmt.Sprintf("filematchlimit:%d", p.FileMatchLimit))
}
for _, lang := range p.Languages {
args = append(args, fmt.Sprintf("lang:%s", lang))
}
path := "glob"
if p.PathPatternsAreRegExps {
path = "f"
}
if p.PathPatternsAreCaseSensitive {
path = "F"
}
if p.ExcludePattern != "" {
args = append(args, fmt.Sprintf("-%s:%q", path, p.ExcludePattern))
}
for _, inc := range p.IncludePatterns {
args = append(args, fmt.Sprintf("%s:%q", path, inc))
}
return fmt.Sprintf("PatternInfo{%s}", strings.Join(args, ","))
}
// Response represents the response from a Search request.
type Response struct {
Matches []FileMatch
// LimitHit is true if Matches may not include all FileMatches because a match limit was hit.
LimitHit bool
// DeadlineHit is true if Matches may not include all FileMatches because a deadline was hit.
DeadlineHit bool
}
// FileMatch is the struct used by vscode to receive search results
type FileMatch struct {
Path string
LineMatches []LineMatch
// MatchCount is the number of matches. Different from len(LineMatches), as multiple lines may correspond to one logical match.
MatchCount int
// LimitHit is true if LineMatches may not include all LineMatches.
LimitHit bool
}
// LineMatch is the struct used by vscode to receive search results for a line.
type LineMatch struct {
// Preview is the matched line.
Preview string
// LineNumber is the 0-based line number. Note: Our editors present
// 1-based line numbers, but internally vscode uses 0-based.
LineNumber int
// OffsetAndLengths is a slice of 2-tuples (Offset, Length)
// representing each match on a line.
// Offsets and lengths are measured in characters, not bytes.
OffsetAndLengths [][2]int
// LimitHit is true if OffsetAndLengths may not include all OffsetAndLengths.
LimitHit bool
}