This repository has been archived by the owner on Apr 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathsourcegraphSearchProvider.ts
108 lines (93 loc) · 3.27 KB
/
sourcegraphSearchProvider.ts
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
'use strict';
import {
CancellationToken,
FileSearchOptions,
FileSearchProvider,
FileSearchQuery,
Progress,
TextSearchComplete,
TextSearchOptions,
TextSearchProvider,
TextSearchQuery,
TextSearchResult,
Uri
} from 'vscode';
import * as fuzzySort from 'fuzzysort';
import { SourcegraphApi } from './sourcegraphApi';
import { Iterables } from './system/iterable';
import { joinPath } from './uris';
const replaceBackslashRegex = /\\/g;
export class SourceGraphSearchProvider implements FileSearchProvider, TextSearchProvider {
private _cache = new Map<string, Fuzzysort.Prepared[]>();
constructor(private readonly _sourcegraph: SourcegraphApi) {}
async provideFileSearchResults(
query: FileSearchQuery,
options: FileSearchOptions,
token: CancellationToken
): Promise<Uri[]> {
let searchable = this._cache.get(options.folder.toString(true));
if (searchable === undefined) {
const matches = await this._sourcegraph.filesQuery(options.folder);
if (matches === undefined || token.isCancellationRequested) return [];
searchable = [...Iterables.map(matches, m => (fuzzySort as any).prepareSlow(m)! as Fuzzysort.Prepared)];
this._cache.set(options.folder.toString(true), searchable);
}
if (options.maxResults == null || options.maxResults === 0 || options.maxResults >= searchable.length) {
const results = searchable.map(m => joinPath(options.folder, m.target));
return results;
}
const results = fuzzySort
.go(query.pattern.replace(replaceBackslashRegex, '/'), searchable, {
allowTypo: true,
limit: options.maxResults
})
.map((m: any) => joinPath(options.folder, m.target));
(fuzzySort as any).cleanup();
return results;
}
async provideTextSearchResults(
query: TextSearchQuery,
options: TextSearchOptions,
progress: Progress<TextSearchResult>,
token: CancellationToken
): Promise<TextSearchComplete> {
let sgQuery;
if (query.isRegExp) {
if (query.isWordMatch) {
sgQuery = `\\b${query.pattern}\\b`;
}
else {
sgQuery = query.pattern;
}
}
else if (query.isWordMatch) {
sgQuery = `\\b${query.pattern}\\b`;
}
else {
sgQuery = `"${query.pattern}"`;
}
if (query.isCaseSensitive) {
sgQuery = ` case:yes ${sgQuery}`;
}
const results = await this._sourcegraph.searchQuery(
sgQuery,
options.folder,
{ maxResults: options.maxResults, context: { before: options.beforeContext, after: options.afterContext } },
token
);
if (results === undefined) return { limitHit: true };
let uri;
for (const m of results.matches) {
uri = joinPath(options.folder, m.path);
progress.report({
uri: uri,
ranges: m.ranges,
preview: {
text: m.preview,
matches: m.matches
}
});
}
return { limitHit: false };
}
}