@@ -2,6 +2,7 @@ package codenav
2
2
3
3
import (
4
4
"context"
5
+ "strings"
5
6
"testing"
6
7
7
8
genslices "github.com/life4/genesis/slices"
@@ -13,6 +14,10 @@ import (
13
14
lsifstoremocks "github.com/sourcegraph/sourcegraph/internal/codeintel/codenav/internal/lsifstore/mocks"
14
15
"github.com/sourcegraph/sourcegraph/internal/codeintel/core"
15
16
uploadsshared "github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
17
+ "github.com/sourcegraph/sourcegraph/internal/search"
18
+ searchClient "github.com/sourcegraph/sourcegraph/internal/search/client"
19
+ "github.com/sourcegraph/sourcegraph/internal/search/result"
20
+ "github.com/sourcegraph/sourcegraph/internal/search/streaming"
16
21
"github.com/sourcegraph/sourcegraph/lib/errors"
17
22
)
18
23
@@ -152,38 +157,55 @@ func shiftPos(pos scip.Position, numLines int32) scip.Position {
152
157
153
158
// A GitTreeTranslator that returns positions and ranges shifted by numLines
154
159
// and returns failed translations for path/range pairs if shouldFail returns true
155
- func fakeTranslator (
160
+ type fakeTranslator struct {
161
+ from api.CommitID
162
+ to api.CommitID
163
+ numLines int
164
+ shouldFail func (core.RepoRelPath , scip.Range ) bool
165
+ }
166
+
167
+ func (t fakeTranslator ) TranslatePosition (ctx context.Context , from , to api.CommitID , path core.RepoRelPath , pos scip.Position ) (core.Option [scip.Position ], error ) {
168
+ numLines := t .numLines
169
+ if from == t .to && to == t .from {
170
+ numLines = - numLines
171
+ }
172
+ if t .shouldFail (path , scip.Range {Start : pos , End : pos }) {
173
+ return core .None [scip.Position ](), nil
174
+ }
175
+ return core .Some (shiftPos (pos , int32 (numLines ))), nil
176
+ }
177
+
178
+ func (t fakeTranslator ) TranslateRange (ctx context.Context , from , to api.CommitID , path core.RepoRelPath , r scip.Range ) (core.Option [scip.Range ], error ) {
179
+ numLines := t .numLines
180
+ if from == t .to && to == t .from {
181
+ numLines = - numLines
182
+ }
183
+ if t .shouldFail (path , r ) {
184
+ return core .None [scip.Range ](), nil
185
+ }
186
+ return core .Some (shiftSCIPRange (r , numLines )), nil
187
+ }
188
+
189
+ func (t fakeTranslator ) Prefetch (ctx context.Context , from api.CommitID , to api.CommitID , paths []core.RepoRelPath ) {
190
+ return
191
+ }
192
+
193
+ func NewFakeTranslator (
156
194
from , to api.CommitID ,
157
195
numLines int ,
158
196
shouldFail func (core.RepoRelPath , scip.Range ) bool ,
159
197
) GitTreeTranslator {
160
- translator := NewMockGitTreeTranslator ()
161
- translator .TranslatePositionFunc .SetDefaultHook (func (ctx context.Context , f , t api.CommitID , path core.RepoRelPath , pos scip.Position ) (core.Option [scip.Position ], error ) {
162
- numLines := numLines
163
- if f == to && t == from {
164
- numLines = - numLines
165
- }
166
- if shouldFail (path , scip.Range {Start : pos , End : pos }) {
167
- return core .None [scip.Position ](), nil
168
- }
169
- return core .Some (shiftPos (pos , int32 (numLines ))), nil
170
- })
171
- translator .TranslateRangeFunc .SetDefaultHook (func (ctx context.Context , f , t api.CommitID , path core.RepoRelPath , range_ scip.Range ) (core.Option [scip.Range ], error ) {
172
- numLines := numLines
173
- if f == to && t == from {
174
- numLines = - numLines
175
- }
176
- if shouldFail (path , range_ ) {
177
- return core .None [scip.Range ](), nil
178
- }
179
- return core .Some (shiftSCIPRange (range_ , numLines )), nil
180
- })
181
- return translator
198
+ return fakeTranslator {
199
+ from : from ,
200
+ to : to ,
201
+ numLines : numLines ,
202
+ shouldFail : shouldFail ,
203
+ }
182
204
}
183
205
184
206
// A GitTreeTranslator that returns all positions and ranges shifted by numLines.
185
207
func shiftAllTranslator (from , to api.CommitID , numLines int ) GitTreeTranslator {
186
- return fakeTranslator (from , to , numLines , func (path core.RepoRelPath , range_ scip.Range ) bool { return false })
208
+ return NewFakeTranslator (from , to , numLines , func (path core.RepoRelPath , range_ scip.Range ) bool { return false })
187
209
}
188
210
189
211
// A GitTreeTranslator that returns all positions and ranges unchanged
@@ -238,3 +260,94 @@ func expectDefinitionRanges[T MatchLike](t *testing.T, matches []T, ranges ...sc
238
260
}
239
261
}
240
262
}
263
+
264
+ func scipToResultPosition (p scip.Position ) result.Location {
265
+ return result.Location {
266
+ Line : int (p .Line ),
267
+ Column : int (p .Character ),
268
+ }
269
+ }
270
+
271
+ func scipToResultRange (r scip.Range ) result.Range {
272
+ return result.Range {
273
+ Start : scipToResultPosition (r .Start ),
274
+ End : scipToResultPosition (r .End ),
275
+ }
276
+ }
277
+
278
+ // scipToSymbolMatch "reverse engineers" the lsp.Range function on result.Symbol
279
+ func scipToSymbolMatch (r scip.Range ) * result.SymbolMatch {
280
+ return & result.SymbolMatch {
281
+ Symbol : result.Symbol {
282
+ Line : int (r .Start .Line + 1 ),
283
+ Character : int (r .Start .Character ),
284
+ Name : strings .Repeat ("a" , int (r .End .Character - r .Start .Character )),
285
+ }}
286
+ }
287
+
288
+ type FakeSearchBuilder struct {
289
+ fileMatches []result.Match
290
+ symbolMatches []result.Match
291
+ }
292
+
293
+ func FakeSearchClient () FakeSearchBuilder {
294
+ return FakeSearchBuilder {
295
+ fileMatches : []result.Match {},
296
+ symbolMatches : make ([]result.Match , 0 ),
297
+ }
298
+ }
299
+
300
+ func ChunkMatchWithLine (range_ scip.Range , line string ) result.ChunkMatch {
301
+ return result.ChunkMatch {
302
+ Ranges : []result.Range {scipToResultRange (range_ )},
303
+ Content : line ,
304
+ ContentStart : result.Location {
305
+ Line : int (range_ .Start .Line ),
306
+ Column : 0 ,
307
+ },
308
+ }
309
+ }
310
+
311
+ func ChunkMatch (range_ scip.Range ) result.ChunkMatch {
312
+ return ChunkMatchWithLine (range_ , "chonky" )
313
+ }
314
+
315
+ func ChunkMatches (ranges ... scip.Range ) []result.ChunkMatch {
316
+ return genslices .Map (ranges , ChunkMatch )
317
+ }
318
+
319
+ func (b FakeSearchBuilder ) WithFile (file string , matches ... result.ChunkMatch ) FakeSearchBuilder {
320
+ b .fileMatches = append (b .fileMatches , & result.FileMatch {
321
+ File : result.File {Path : file },
322
+ ChunkMatches : matches ,
323
+ })
324
+ return b
325
+ }
326
+
327
+ func (b FakeSearchBuilder ) WithSymbols (file string , ranges ... scip.Range ) FakeSearchBuilder {
328
+ b .symbolMatches = append (b .symbolMatches , & result.FileMatch {
329
+ File : result.File {Path : file },
330
+ Symbols : genslices .Map (ranges , scipToSymbolMatch ),
331
+ })
332
+ return b
333
+ }
334
+
335
+ func (b FakeSearchBuilder ) Build () searchClient.SearchClient {
336
+ mockSearchClient := searchClient .NewMockSearchClient ()
337
+ mockSearchClient .PlanFunc .SetDefaultHook (func (_ context.Context , _ string , _ * string , query string , _ search.Mode , _ search.Protocol , _ * int32 ) (* search.Inputs , error ) {
338
+ return & search.Inputs {OriginalQuery : query }, nil
339
+ })
340
+ mockSearchClient .ExecuteFunc .SetDefaultHook (func (_ context.Context , s streaming.Sender , i * search.Inputs ) (* search.Alert , error ) {
341
+ if strings .Contains (i .OriginalQuery , "type:file" ) {
342
+ s .Send (streaming.SearchEvent {
343
+ Results : b .fileMatches ,
344
+ })
345
+ } else if strings .Contains (i .OriginalQuery , "type:symbol" ) {
346
+ s .Send (streaming.SearchEvent {
347
+ Results : b .symbolMatches ,
348
+ })
349
+ }
350
+ return nil , nil
351
+ })
352
+ return mockSearchClient
353
+ }
0 commit comments