-
Notifications
You must be signed in to change notification settings - Fork 0
/
querier.go
115 lines (99 loc) · 2.49 KB
/
querier.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
package main
import (
"sort"
)
const (
// Filter types for query results
// ResultsAll is no filter on type
ResultsAll = "all"
// ResultsFunctions filters on functions
ResultsFunctions = "functions"
// ResultsStructs filters on structs
ResultsStructs = "structs"
// ResultsVariables filters on variables
ResultsVariables = "variables"
// DefaultResultsLimit defines the number of results to return for query
DefaultResultsLimit = 10
)
// QueryOptions defines filters and other options for querying
type QueryOptions struct {
wtype string
file string
limit int
}
// DefaultQueryOptions returns default settings for QueryOptions which is no
// filtering and a result limit 10
func DefaultQueryOptions() *QueryOptions {
return &QueryOptions{
wtype: ResultsAll,
file: ResultsAll,
limit: DefaultResultsLimit,
}
}
// Querier manages the logic for returning search results
type Querier struct {
idx *Index
trie *Trie
}
// NewQuerier returns a Querier object initialized with an Index and a Trie
func NewQuerier(idx *Index, trie *Trie) *Querier {
return &Querier{
idx,
trie,
}
}
// Query runs a query for the input and returns a list of References
func (q *Querier) Query(input string, opts *QueryOptions) References {
n, ok := q.trie.Find(input)
if !ok {
return nil
}
var results []Reference
words := n.Prefixes()
for _, w := range words {
w = input + w
refs, ok := q.idx.ReferencesByWord(w)
if !ok {
continue
}
results = append(results, refs...)
}
// filter if needed
resultsFiltered := results
if opts.file != ResultsAll || opts.wtype != ResultsAll {
resultsFiltered = []Reference{}
for _, res := range results {
if isMatch(res, opts) {
resultsFiltered = append(resultsFiltered, res)
}
}
}
sort.Sort(sort.Reverse(SmartSort(resultsFiltered)))
if len(resultsFiltered) > opts.limit {
resultsFiltered = resultsFiltered[:opts.limit]
}
return resultsFiltered
}
// returns true if the reference is a match on the filter and false otherwise.
// References that do not match are filtered out.
func isMatch(ref Reference, opts *QueryOptions) bool {
if opts.wtype != ResultsAll {
// filter on type
switch ref.(type) {
case *Function:
if opts.wtype != ResultsFunctions {
return false
}
case *Variable:
if opts.wtype != ResultsVariables {
return false
}
case *Struct:
if opts.wtype != ResultsStructs {
return false
}
}
}
// filter on file location
return opts.file == ResultsAll || ref.GetLocation().File == opts.file
}