fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

Emit errors for overly general regexp queries.

+135 -21
+5
parse.go
··· 200 200 return nil, err 201 201 } 202 202 203 + substrQ := regexpToQuery(r) 204 + if v, ok := isConst(substrQ); ok && v { 205 + return nil, fmt.Errorf("regexp %s is too general. Need at least %d consecutive characters", arg, ngramSize) 206 + } 207 + 203 208 add(&RegexpQuery{ 204 209 Regexp: r, 205 210 })
+2 -1
parse_test.go
··· 45 45 &SubstringQuery{Pattern: "bcd"}, 46 46 }}, false}, 47 47 {"-abc", &NotQuery{&SubstringQuery{Pattern: "abc"}}, false}, 48 + {"regex:a.b", nil, true}, 48 49 49 50 {"abccase:yes", &SubstringQuery{Pattern: "abccase:yes"}, false}, 50 51 {"file:abc", &SubstringQuery{Pattern: "abc", FileName: true}, false}, ··· 70 71 } { 71 72 q, err := Parse(c.in) 72 73 if c.hasErr != (err != nil) { 73 - t.Errorf("Parse(%s): error %v", c.in, err) 74 + t.Errorf("Parse(%s): error %v, value %v", c.in, err, q) 74 75 } else if q != nil { 75 76 if !reflect.DeepEqual(q, c.out) { 76 77 t.Errorf("Parse(%s): got %v want %v", c.in, q, c.out)
+78
query.go
··· 38 38 return fmt.Sprintf("regex:%q", q.Regexp.String()) 39 39 } 40 40 41 + type TrueQuery struct{} 42 + 43 + func (q *TrueQuery) String() string { 44 + return "TRUE" 45 + } 46 + 47 + type FalseQuery struct{} 48 + 49 + func (q *FalseQuery) String() string { 50 + return "FALSE" 51 + } 52 + 41 53 // SubstringQuery is the most basic query: a query for a substring. 42 54 type SubstringQuery struct { 43 55 Pattern string ··· 162 174 return neg 163 175 } 164 176 177 + func isConst(q Query) (bool, bool) { 178 + if _, ok := q.(*TrueQuery); ok { 179 + return true, true 180 + } 181 + if _, ok := q.(*FalseQuery); ok { 182 + return false, true 183 + } 184 + return false, false 185 + } 186 + 187 + func invertConst(q Query) Query { 188 + switch q.(type) { 189 + case *TrueQuery: 190 + return &FalseQuery{} 191 + case *FalseQuery: 192 + return &TrueQuery{} 193 + } 194 + return q 195 + } 196 + 197 + func evalAndOrConstants(q Query, children []Query) Query { 198 + _, isAnd := q.(*AndQuery) 199 + 200 + children = mapQuery(children, evalConstants) 201 + 202 + newCH := children[:0] 203 + for _, ch := range children { 204 + c, ok := isConst(ch) 205 + if ok { 206 + if c == isAnd { 207 + continue 208 + } else { 209 + return ch 210 + } 211 + } 212 + newCH = append(newCH, ch) 213 + } 214 + if len(newCH) == 0 { 215 + if isAnd { 216 + return &TrueQuery{} 217 + } 218 + return &FalseQuery{} 219 + } 220 + if isAnd { 221 + return &AndQuery{newCH} 222 + } 223 + return &OrQuery{newCH} 224 + } 225 + 226 + func evalConstants(q Query) Query { 227 + switch s := q.(type) { 228 + case *AndQuery: 229 + return evalAndOrConstants(q, s.Children) 230 + case *OrQuery: 231 + return evalAndOrConstants(q, s.Children) 232 + case *NotQuery: 233 + ch := evalConstants(s.Child) 234 + if _, ok := isConst(ch); ok { 235 + return invertConst(ch) 236 + } 237 + return &NotQuery{ch} 238 + } 239 + return q 240 + } 241 + 165 242 func simplify(q Query) Query { 243 + q = evalConstants(q) 166 244 for { 167 245 var changed bool 168 246 q, changed = flatten(q)
+37 -17
query_test.go
··· 16 16 17 17 import ( 18 18 "log" 19 + "reflect" 19 20 "testing" 20 21 ) 21 22 ··· 35 36 } 36 37 } 37 38 38 - func TestQueryFlatten(t *testing.T) { 39 - var q Query 40 - q = &OrQuery{[]Query{ 41 - &OrQuery{[]Query{ 42 - &AndQuery{[]Query{ 43 - &SubstringQuery{Pattern: "hoi"}, 44 - &NotQuery{&SubstringQuery{Pattern: "hai"}}, 45 - }}, 46 - &OrQuery{[]Query{ 39 + func TestSimplify(t *testing.T) { 40 + type testcase struct { 41 + in Query 42 + want Query 43 + } 44 + 45 + cases := []testcase{ 46 + { 47 + in: &OrQuery{[]Query{ 48 + &OrQuery{[]Query{ 49 + &AndQuery{[]Query{ 50 + &SubstringQuery{Pattern: "hoi"}, 51 + &NotQuery{&SubstringQuery{Pattern: "hai"}}, 52 + }}, 53 + &OrQuery{[]Query{ 54 + &SubstringQuery{Pattern: "zip"}, 55 + &SubstringQuery{Pattern: "zap"}, 56 + }}, 57 + }}}}, 58 + want: &OrQuery{[]Query{ 59 + &AndQuery{[]Query{ 60 + &SubstringQuery{Pattern: "hoi"}, 61 + &NotQuery{&SubstringQuery{Pattern: "hai"}}, 62 + }}, 47 63 &SubstringQuery{Pattern: "zip"}, 48 - &SubstringQuery{Pattern: "zap"}, 64 + &SubstringQuery{Pattern: "zap"}}, 49 65 }}, 50 - }}}} 66 + {in: &AndQuery{}, want: &TrueQuery{}}, 67 + {in: &OrQuery{}, want: &FalseQuery{}}, 68 + {in: &AndQuery{[]Query{&TrueQuery{}, &FalseQuery{}}}, want: &FalseQuery{}}, 69 + {in: &OrQuery{[]Query{&FalseQuery{}, &TrueQuery{}}}, want: &TrueQuery{}}, 70 + {in: &NotQuery{&TrueQuery{}}, want: &FalseQuery{}}, 71 + } 51 72 52 - q = simplify(q) 53 - got := q.String() 54 - 55 - want := `(or (and substr:"hoi" (not substr:"hai")) substr:"zip" substr:"zap")` 56 - if got != want { 57 - t.Errorf("got %s, want %s", got, want) 73 + for _, c := range cases { 74 + got := simplify(c.in) 75 + if !reflect.DeepEqual(got, c.want) { 76 + t.Errorf("got %s, want %s", got, c.want) 77 + } 58 78 } 59 79 }
+11 -2
regexp.go
··· 1 1 package zoekt 2 2 3 3 import ( 4 + "log" 4 5 "regexp/syntax" 5 6 ) 7 + 8 + var _ = log.Println 6 9 7 10 func lowerRegexp(r *syntax.Regexp) *syntax.Regexp { 8 11 newRE := *r ··· 22 25 return &newRE 23 26 } 24 27 28 + func regexpToQuery(r *syntax.Regexp) Query { 29 + q := regexpToQueryRecursive(r) 30 + q = simplify(q) 31 + return q 32 + } 33 + 25 34 // regexpToQuery tries to distill a substring search query that 26 35 // matches a superset of the regexp. 27 - func regexpToQuery(r *syntax.Regexp) Query { 36 + func regexpToQueryRecursive(r *syntax.Regexp) Query { 28 37 // TODO - we could perhaps transform Begin/EndText in '\n'? 29 38 // TODO - we could perhaps transform CharClass in (OrQuery ) 30 39 // if there are just a few runes, and part of a OpConcat? ··· 57 66 } 58 67 return &OrQuery{qs} 59 68 } 60 - return nil 69 + return &TrueQuery{} 61 70 }
+2 -1
regexp_test.go
··· 44 44 } 45 45 46 46 cases := []testcase{ 47 + {"(foo|)bar", &SubstringQuery{Pattern: "bar"}}, 48 + {"(foo|)", &TrueQuery{}}, 47 49 {"(foo|bar)baz.*bla", &AndQuery{[]Query{ 48 50 &OrQuery{[]Query{ 49 51 &SubstringQuery{Pattern: "foo"}, ··· 52 54 &SubstringQuery{Pattern: "baz"}, 53 55 &SubstringQuery{Pattern: "bla"}, 54 56 }}}, 55 - 56 57 {"^[a-z](People)+barrabas$", 57 58 &AndQuery{[]Query{ 58 59 &SubstringQuery{Pattern: "People"},