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

Configure Feed

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

Split off query processing into query/ package

+469 -407
+3 -1
api.go
··· 17 17 import ( 18 18 "fmt" 19 19 "time" 20 + 21 + "github.com/google/zoekt/query" 20 22 ) 21 23 22 24 // FileMatch contains all the matches within a file. ··· 96 98 } 97 99 98 100 type Searcher interface { 99 - Search(query Query) (*SearchResult, error) 101 + Search(q query.Query) (*SearchResult, error) 100 102 Close() error 101 103 }
+2 -1
cmd/search/main.go
··· 23 23 "runtime/pprof" 24 24 25 25 "github.com/google/zoekt" 26 + "github.com/google/zoekt/query" 26 27 ) 27 28 28 29 const CONTEXT = 20 ··· 62 63 log.Fatal(err) 63 64 } 64 65 65 - query, err := zoekt.Parse(pat) 66 + query, err := query.Parse(pat) 66 67 if err != nil { 67 68 log.Fatal(err) 68 69 }
+8 -6
cmd/server/main.go
··· 27 27 "time" 28 28 29 29 "github.com/google/zoekt" 30 + "github.com/google/zoekt/query" 30 31 ) 31 32 32 33 type httpServer struct { ··· 46 47 func (s *httpServer) serveSearch(w http.ResponseWriter, r *http.Request) { 47 48 err := s.serveSearchErr(w, r) 48 49 49 - if suggest, ok := err.(*zoekt.SuggestQueryError); ok { 50 + if suggest, ok := err.(*query.SuggestQueryError); ok { 50 51 var buf bytes.Buffer 51 52 if err := didYouMeanTemplate.Execute(&buf, suggest); err != nil { 52 53 http.Error(w, err.Error(), http.StatusTeapot) ··· 159 160 160 161 func (s *httpServer) serveSearchErr(w http.ResponseWriter, r *http.Request) error { 161 162 qvals := r.URL.Query() 162 - query := qvals.Get("q") 163 - q, err := zoekt.Parse(query) 163 + queryStr := qvals.Get("q") 164 + if queryStr == "" { 165 + return fmt.Errorf("no query found") 166 + } 167 + 168 + q, err := query.Parse(queryStr) 164 169 if err != nil { 165 170 return err 166 171 } 167 172 168 173 numStr := qvals.Get("num") 169 - if query == "" { 170 - return fmt.Errorf("no query found") 171 - } 172 174 173 175 num, err := strconv.Atoi(numStr) 174 176 if err != nil {
+3 -1
dociter.go
··· 19 19 "fmt" 20 20 "log" 21 21 "sort" 22 + 23 + "github.com/google/zoekt/query" 22 24 ) 23 25 24 26 var _ = log.Println 25 27 26 28 type docIterator struct { 27 - query *SubstringQuery 29 + query *query.Substring 28 30 29 31 leftPad uint32 30 32 rightPad uint32
+27 -25
eval.go
··· 4 4 "fmt" 5 5 "log" 6 6 "regexp" 7 + 8 + "github.com/google/zoekt/query" 7 9 ) 8 10 9 11 var _ = log.Println ··· 32 34 } 33 35 34 36 type regexpMatchTree struct { 35 - query *RegexpQuery 37 + query *query.Regexp 36 38 regexp *regexp.Regexp 37 39 child matchTree 38 40 ··· 42 44 } 43 45 44 46 type substrMatchTree struct { 45 - query *SubstringQuery 47 + query *query.Substring 46 48 47 49 cands []*candidateMatch 48 50 coversContent bool ··· 310 312 return true, sure 311 313 } 312 314 313 - func (d *indexData) newMatchTree(q Query, sq map[*SubstringQuery]*substrMatchTree) (matchTree, error) { 315 + func (d *indexData) newMatchTree(q query.Query, sq map[*query.Substring]*substrMatchTree) (matchTree, error) { 314 316 switch s := q.(type) { 315 - case *RegexpQuery: 316 - subQ := regexpToQuery(s.Regexp) 317 + case *query.Regexp: 318 + subQ := query.RegexpToQuery(s.Regexp) 317 319 subMT, err := d.newMatchTree(subQ, sq) 318 320 if err != nil { 319 321 return nil, err ··· 323 325 regexp: regexp.MustCompile(s.Regexp.String()), 324 326 child: subMT, 325 327 }, nil 326 - case *AndQuery: 328 + case *query.And: 327 329 var r []matchTree 328 330 for _, ch := range s.Children { 329 331 ct, err := d.newMatchTree(ch, sq) ··· 333 335 r = append(r, ct) 334 336 } 335 337 return &andMatchTree{r}, nil 336 - case *OrQuery: 338 + case *query.Or: 337 339 var r []matchTree 338 340 for _, ch := range s.Children { 339 341 ct, err := d.newMatchTree(ch, sq) ··· 343 345 r = append(r, ct) 344 346 } 345 347 return &andMatchTree{r}, nil 346 - case *NotQuery: 348 + case *query.Not: 347 349 ct, err := d.newMatchTree(s.Child, sq) 348 350 return &notMatchTree{ 349 351 child: ct, 350 352 }, err 351 - case *SubstringQuery: 353 + case *query.Substring: 352 354 iter, err := d.getDocIterator(s) 353 355 if err != nil { 354 356 return nil, err ··· 361 363 sq[s] = st 362 364 return st, nil 363 365 364 - case *BranchQuery: 366 + case *query.Branch: 365 367 return &branchQueryMatchTree{ 366 368 mask: uint32(d.branchIDs[s.Name]), 367 369 fileMasks: d.fileBranchMasks, 368 370 }, nil 369 371 } 370 - panic("type") 372 + log.Panicf("type %T", q) 371 373 return nil, nil 372 374 } 373 375 374 - func (d *indexData) simplify(in Query) Query { 375 - eval := mapQuery(in, func(q Query) Query { 376 - if r, ok := q.(*RepoQuery); ok { 377 - return constQuery(r.Name == d.repoName) 376 + func (d *indexData) simplify(in query.Query) query.Query { 377 + eval := query.Map(in, func(q query.Query) query.Query { 378 + if r, ok := q.(*query.Repo); ok { 379 + return &query.Const{r.Name == d.repoName} 378 380 } 379 381 return q 380 382 }) 381 - return simplify(eval) 383 + return query.Simplify(eval) 382 384 } 383 385 384 - func (d *indexData) Search(q Query) (*SearchResult, error) { 386 + func (d *indexData) Search(q query.Query) (*SearchResult, error) { 385 387 var res SearchResult 386 388 387 389 q = d.simplify(q) 388 - if c, ok := isConst(q); ok && !c { 390 + if c, ok := q.(*query.Const); ok && !c.Value { 389 391 return &res, nil 390 392 } 391 393 392 - atoms := map[*SubstringQuery]*substrMatchTree{} 394 + atoms := map[*query.Substring]*substrMatchTree{} 393 395 mt, err := d.newMatchTree(q, atoms) 394 396 if err != nil { 395 397 return nil, err ··· 567 569 return &res, nil 568 570 } 569 571 570 - func extractSubstringQueries(q Query) []*SubstringQuery { 571 - var r []*SubstringQuery 572 + func extractSubstringQueries(q query.Query) []*query.Substring { 573 + var r []*query.Substring 572 574 switch s := q.(type) { 573 - case *AndQuery: 575 + case *query.And: 574 576 for _, ch := range s.Children { 575 577 r = append(r, extractSubstringQueries(ch)...) 576 578 } 577 - case *OrQuery: 579 + case *query.Or: 578 580 for _, ch := range s.Children { 579 581 r = append(r, extractSubstringQueries(ch)...) 580 582 } 581 - case *NotQuery: 583 + case *query.Not: 582 584 r = append(r, extractSubstringQueries(s.Child)...) 583 - case *SubstringQuery: 585 + case *query.Substring: 584 586 r = append(r, s) 585 587 } 586 588 return r
+4 -3
index.go
··· 16 16 17 17 import ( 18 18 "fmt" 19 + "github.com/google/zoekt/query" 19 20 "log" 20 21 "strings" 21 22 ) ··· 51 52 repoName string 52 53 } 53 54 54 - func (data *indexData) getDocIterator(query *SubstringQuery) (*docIterator, error) { 55 + func (data *indexData) getDocIterator(query *query.Substring) (*docIterator, error) { 55 56 if len(query.Pattern) < ngramSize { 56 57 return nil, fmt.Errorf("pattern %q less than %d bytes", query.Pattern, ngramSize) 57 58 } ··· 62 63 return data.getContentDocIterator(query) 63 64 } 64 65 65 - func (data *indexData) getFileNameDocIterator(query *SubstringQuery) *docIterator { 66 + func (data *indexData) getFileNameDocIterator(query *query.Substring) *docIterator { 66 67 str := strings.ToLower(query.Pattern) // TODO - UTF-8 67 68 di := &docIterator{ 68 69 query: query, ··· 89 90 return uint32(j) 90 91 } 91 92 92 - func (data *indexData) getContentDocIterator(query *SubstringQuery) (*docIterator, error) { 93 + func (data *indexData) getContentDocIterator(query *query.Substring) (*docIterator, error) { 93 94 str := strings.ToLower(query.Pattern) // TODO - UTF-8 94 95 input := &docIterator{ 95 96 query: query,
+52 -40
index_test.go
··· 20 20 "io" 21 21 "log" 22 22 "reflect" 23 + "regexp/syntax" 23 24 "testing" 25 + 26 + "github.com/google/zoekt/query" 24 27 ) 25 28 26 29 func clearScores(r *SearchResult) { ··· 39 42 b.AddFile("f1", []byte("reader")) 40 43 searcher := searcherForTest(t, b) 41 44 42 - res, err := searcher.Search(&SubstringQuery{Pattern: "there"}) 45 + res, err := searcher.Search(&query.Substring{Pattern: "there"}) 43 46 if err != nil { 44 47 t.Errorf("search: %v", err) 45 48 } ··· 58 61 // -------------------- 0123456789012345678901234567890123456789 59 62 60 63 searcher := searcherForTest(t, b) 61 - res, err := searcher.Search(&SubstringQuery{Pattern: "water"}) 64 + res, err := searcher.Search(&query.Substring{Pattern: "water"}) 62 65 if err != nil { 63 66 t.Errorf("search: %v", err) 64 67 } ··· 117 120 //----------------------------012345 678901 23456 118 121 119 122 searcher := searcherForTest(t, b) 120 - sres, err := searcher.Search(&SubstringQuery{Pattern: "ne2"}) 123 + sres, err := searcher.Search(&query.Substring{Pattern: "ne2"}) 121 124 if err != nil { 122 125 t.Fatal(err) 123 126 } ··· 210 213 b.AddFile("f2", c2) 211 214 212 215 searcher := searcherForTest(t, b) 213 - sres, err := searcher.Search(&SubstringQuery{Pattern: "ananas"}) 216 + sres, err := searcher.Search(&query.Substring{Pattern: "ananas"}) 214 217 if err != nil { 215 218 t.Fatalf("Search: %v", err) 216 219 } ··· 234 237 235 238 searcher := searcherForTest(t, b) 236 239 sres, err := searcher.Search( 237 - &SubstringQuery{ 240 + &query.Substring{ 238 241 Pattern: "bananas", 239 242 CaseSensitive: true, 240 243 }) ··· 247 250 } 248 251 249 252 sres, err = searcher.Search( 250 - &SubstringQuery{ 253 + &query.Substring{ 251 254 Pattern: "BaNaNAS", 252 255 CaseSensitive: true, 253 256 }) ··· 271 274 // ---------------------0123456789012345 272 275 searcher := searcherForTest(t, b) 273 276 sres, err := searcher.Search( 274 - &AndQuery{ 275 - Children: []Query{ 276 - &SubstringQuery{ 277 + &query.And{ 278 + Children: []query.Query{ 279 + &query.Substring{ 277 280 Pattern: "banana", 278 281 }, 279 - &SubstringQuery{ 282 + &query.Substring{ 280 283 Pattern: "apple", 281 284 }, 282 285 }, ··· 315 318 // ---------------------0123456789012345 316 319 searcher := searcherForTest(t, b) 317 320 sres, err := searcher.Search( 318 - &AndQuery{ 319 - Children: []Query{ 320 - &SubstringQuery{ 321 + &query.And{ 322 + Children: []query.Query{ 323 + &query.Substring{ 321 324 Pattern: "banana", 322 325 }, 323 - &NotQuery{&SubstringQuery{ 326 + &query.Not{&query.Substring{ 324 327 Pattern: "apple", 325 328 }}, 326 329 }, ··· 353 356 354 357 searcher := searcherForTest(t, b) 355 358 sres, err := searcher.Search( 356 - &AndQuery{ 357 - Children: []Query{ 358 - &SubstringQuery{ 359 + &query.And{ 360 + Children: []query.Query{ 361 + &query.Substring{ 359 362 Pattern: "banana", 360 363 }, 361 - &NotQuery{&SubstringQuery{ 364 + &query.Not{&query.Substring{ 362 365 Pattern: "appel", 363 366 }}, 364 367 }, ··· 381 384 searcher := searcherForTest(t, b) 382 385 383 386 sres, err := searcher.Search( 384 - &SubstringQuery{ 387 + &query.Substring{ 385 388 Pattern: "anan", 386 389 FileName: true, 387 390 }) ··· 419 422 searcher := searcherForTest(t, b) 420 423 421 424 sres, err := searcher.Search( 422 - &AndQuery{[]Query{ 423 - &SubstringQuery{ 425 + &query.And{[]query.Query{ 426 + &query.Substring{ 424 427 Pattern: "banana", 425 428 FileName: true, 426 429 }, 427 - &SubstringQuery{ 430 + &query.Substring{ 428 431 Pattern: "apple", 429 432 }, 430 433 }}) ··· 454 457 searcher := searcherForTest(t, b) 455 458 456 459 sres, err := searcher.Search( 457 - &SubstringQuery{ 460 + &query.Substring{ 458 461 Pattern: "helpers.go", 459 462 FileName: true, 460 463 }) ··· 480 483 searcher := searcherForTest(t, b) 481 484 482 485 sres, err := searcher.Search( 483 - &SubstringQuery{ 486 + &query.Substring{ 484 487 Pattern: "byte", 485 488 }) 486 489 if err != nil { ··· 506 509 searcher := searcherForTest(t, b) 507 510 508 511 sres, err := searcher.Search( 509 - &AndQuery{[]Query{ 510 - &SubstringQuery{ 512 + &query.And{[]query.Query{ 513 + &query.Substring{ 511 514 Pattern: "needle", 512 515 }, 513 - &BranchQuery{ 516 + &query.Branch{ 514 517 Name: "stable", 515 518 }, 516 519 }}) ··· 535 538 b.AddFileBranches("f2", []byte("needle"), branches) 536 539 searcher := searcherForTest(t, b) 537 540 sres, err := searcher.Search( 538 - &SubstringQuery{ 541 + &query.Substring{ 539 542 Pattern: "needle", 540 543 }) 541 544 if err != nil { ··· 560 563 561 564 searcher := searcherForTest(t, b) 562 565 sres, err := searcher.Search( 563 - &AndQuery{ 564 - Children: []Query{ 565 - &SubstringQuery{ 566 + &query.And{ 567 + Children: []query.Query{ 568 + &query.Substring{ 566 569 Pattern: "needle", 567 570 }, 568 - &NotQuery{&SubstringQuery{ 571 + &query.Not{&query.Substring{ 569 572 Pattern: "the", 570 573 }}, 571 574 }, ··· 580 583 } 581 584 } 582 585 586 + func mustParseRE(s string) *syntax.Regexp { 587 + r, err := syntax.Parse(s, 0) 588 + if err != nil { 589 + panic(err) 590 + } 591 + 592 + return r 593 + } 594 + 583 595 func TestRegexp(t *testing.T) { 584 596 b := NewIndexBuilder() 585 597 ··· 589 601 590 602 searcher := searcherForTest(t, b) 591 603 sres, err := searcher.Search( 592 - &RegexpQuery{ 604 + &query.Regexp{ 593 605 mustParseRE("dle.*bla"), 594 606 }) 595 607 ··· 627 639 628 640 searcher := searcherForTest(t, b) 629 641 sres, err := searcher.Search( 630 - &RegexpQuery{ 642 + &query.Regexp{ 631 643 mustParseRE("dle.*bla"), 632 644 }) 633 645 ··· 650 662 651 663 searcher := searcherForTest(t, b) 652 664 sres, err := searcher.Search( 653 - &AndQuery{[]Query{ 654 - &SubstringQuery{Pattern: "needle"}, 655 - &RepoQuery{Name: "foo"}, 665 + &query.And{[]query.Query{ 666 + &query.Substring{Pattern: "needle"}, 667 + &query.Repo{Name: "foo"}, 656 668 }}) 657 669 if err != nil { 658 670 t.Fatalf("Search: %v", err) ··· 666 678 } 667 679 668 680 sres, err = searcher.Search( 669 - &AndQuery{[]Query{ 670 - &SubstringQuery{Pattern: "needle"}, 671 - &RepoQuery{Name: "bla"}, 681 + &query.And{[]query.Query{ 682 + &query.Substring{Pattern: "needle"}, 683 + &query.Repo{Name: "bla"}, 672 684 }}) 673 685 if err != nil { 674 686 t.Fatalf("Search: %v", err)
+14 -12
parse.go query/parse.go
··· 12 12 // See the License for the specific language governing permissions and 13 13 // limitations under the License. 14 14 15 - package zoekt 15 + package query 16 16 17 17 import ( 18 18 "bytes" ··· 22 22 ) 23 23 24 24 var _ = log.Printf 25 + 26 + const ngramSize = 3 25 27 26 28 type SuggestQueryError struct { 27 29 Message string ··· 151 153 var current []byte 152 154 add := func(q Query) { 153 155 if negate { 154 - q = &NotQuery{q} 156 + q = &Not{q} 155 157 } 156 158 qs = append(qs, q) 157 159 negate = false ··· 179 181 if fn, n, ok, err := tryConsumeFile(b); err != nil { 180 182 return nil, err 181 183 } else if ok { 182 - add(&SubstringQuery{ 184 + add(&Substring{ 183 185 Pattern: fn, 184 186 FileName: true, 185 187 }) ··· 190 192 if fn, n, ok, err := tryConsumeRepo(b); err != nil { 191 193 return nil, err 192 194 } else if ok { 193 - add(&RepoQuery{Name: fn}) 195 + add(&Repo{Name: fn}) 194 196 b = b[n:] 195 197 continue 196 198 } ··· 198 200 if fn, n, ok, err := tryConsumeBranch(b); err != nil { 199 201 return nil, err 200 202 } else if ok { 201 - add(&BranchQuery{ 203 + add(&Branch{ 202 204 Name: fn, 203 205 }) 204 206 b = b[n:] ··· 213 215 return nil, err 214 216 } 215 217 216 - substrQ := regexpToQuery(r) 217 - if v, ok := isConst(substrQ); ok && v { 218 + substrQ := RegexpToQuery(r) 219 + if v, ok := substrQ.(*Const); ok && v.Value { 218 220 return nil, fmt.Errorf("regexp %s is too general. Need at least %d consecutive characters", arg, ngramSize) 219 221 } 220 222 221 - add(&RegexpQuery{ 223 + add(&Regexp{ 222 224 Regexp: r, 223 225 }) 224 226 b = b[n:] ··· 240 242 if isSpace(c) { 241 243 inWord = false 242 244 if len(current) > 0 { 243 - add(&SubstringQuery{Pattern: string(current)}) 245 + add(&Substring{Pattern: string(current)}) 244 246 current = current[:0] 245 247 } 246 248 b = b[1:] ··· 253 255 } 254 256 255 257 if len(current) > 0 { 256 - add(&SubstringQuery{Pattern: string(current)}) 258 + add(&Substring{Pattern: string(current)}) 257 259 } 258 260 259 261 for _, q := range qs { 260 - if sq, ok := q.(*SubstringQuery); ok { 262 + if sq, ok := q.(*Substring); ok { 261 263 if len(sq.Pattern) < 3 { 262 264 return nil, &SuggestQueryError{ 263 265 fmt.Sprintf("pattern %q too short", sq.Pattern), ··· 283 285 return qs[0], nil 284 286 } 285 287 286 - return &AndQuery{qs}, nil 288 + return &And{qs}, nil 287 289 }
-82
parse_test.go
··· 1 - // Copyright 2016 Google Inc. All rights reserved. 2 - // 3 - // Licensed under the Apache License, Version 2.0 (the "License"); 4 - // you may not use this file except in compliance with the License. 5 - // You may obtain a copy of the License at 6 - // 7 - // http://www.apache.org/licenses/LICENSE-2.0 8 - // 9 - // Unless required by applicable law or agreed to in writing, software 10 - // distributed under the License is distributed on an "AS IS" BASIS, 11 - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 - // See the License for the specific language governing permissions and 13 - // limitations under the License. 14 - 15 - package zoekt 16 - 17 - import ( 18 - "reflect" 19 - "regexp/syntax" 20 - "testing" 21 - ) 22 - 23 - func mustParseRE(s string) *syntax.Regexp { 24 - r, err := syntax.Parse(s, 0) 25 - if err != nil { 26 - panic(err) 27 - } 28 - 29 - return r 30 - } 31 - 32 - func TestParseQuery(t *testing.T) { 33 - type testcase struct { 34 - in string 35 - out Query 36 - hasErr bool 37 - } 38 - 39 - for _, c := range []testcase{ 40 - {"sub-pixel", &SubstringQuery{Pattern: "sub-pixel"}, false}, 41 - {"abc", &SubstringQuery{Pattern: "abc"}, false}, 42 - {"\"abc bcd\"", &SubstringQuery{Pattern: "abc bcd"}, false}, 43 - {"abc bcd", &AndQuery{[]Query{ 44 - &SubstringQuery{Pattern: "abc"}, 45 - &SubstringQuery{Pattern: "bcd"}, 46 - }}, false}, 47 - {"-abc", &NotQuery{&SubstringQuery{Pattern: "abc"}}, false}, 48 - {"regex:a.b", nil, true}, 49 - 50 - {"abccase:yes", &SubstringQuery{Pattern: "abccase:yes"}, false}, 51 - {"file:abc", &SubstringQuery{Pattern: "abc", FileName: true}, false}, 52 - {"branch:pqr", &BranchQuery{Name: "pqr"}, false}, 53 - 54 - {"file:helpers.go byte", &AndQuery{[]Query{ 55 - &SubstringQuery{Pattern: "helpers.go", FileName: true}, 56 - &SubstringQuery{Pattern: "byte"}, 57 - }}, false}, 58 - 59 - {"regex:abc[p-q]", &RegexpQuery{mustParseRE("abc[p-q]")}, false}, 60 - {"repo:go", &RepoQuery{"go"}, false}, 61 - 62 - // case 63 - {"abc case:yes", &SubstringQuery{Pattern: "abc", CaseSensitive: true}, false}, 64 - {"abc case:auto", &SubstringQuery{Pattern: "abc", CaseSensitive: false}, false}, 65 - {"ABC case:auto", &SubstringQuery{Pattern: "ABC", CaseSensitive: true}, false}, 66 - {"ABC case:\"auto\"", &SubstringQuery{Pattern: "ABC", CaseSensitive: true}, false}, 67 - // errors. 68 - {"\"abc", nil, true}, 69 - {"\"a\\", nil, true}, 70 - {"case:foo", nil, true}, 71 - {"", nil, true}, 72 - } { 73 - q, err := Parse(c.in) 74 - if c.hasErr != (err != nil) { 75 - t.Errorf("Parse(%s): error %v, value %v", c.in, err, q) 76 - } else if q != nil { 77 - if !reflect.DeepEqual(q, c.out) { 78 - t.Errorf("Parse(%s): got %v want %v", c.in, q, c.out) 79 - } 80 - } 81 - } 82 - }
+54 -72
query.go query/query.go
··· 12 12 // See the License for the specific language governing permissions and 13 13 // limitations under the License. 14 14 15 - package zoekt 15 + package query 16 16 17 17 import ( 18 18 "fmt" ··· 30 30 } 31 31 32 32 // RegexpQuery is a query looking for regular expressions matches. 33 - type RegexpQuery struct { 33 + type Regexp struct { 34 34 Regexp *syntax.Regexp 35 35 } 36 36 37 - func (q *RegexpQuery) String() string { 37 + func (q *Regexp) String() string { 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" 41 + type Const struct { 42 + Value bool 45 43 } 46 44 47 - type FalseQuery struct{} 48 - 49 - func (q *FalseQuery) String() string { 45 + func (q *Const) String() string { 46 + if q.Value { 47 + return "TRUE" 48 + } 50 49 return "FALSE" 51 50 } 52 51 53 - type RepoQuery struct { 52 + type Repo struct { 54 53 Name string 55 54 } 56 55 57 - func (q *RepoQuery) String() string { 56 + func (q *Repo) String() string { 58 57 return fmt.Sprintf("repo:%s", q.Name) 59 58 } 60 59 61 - // SubstringQuery is the most basic query: a query for a substring. 62 - type SubstringQuery struct { 60 + // Substring is the most basic query: a query for a substring. 61 + type Substring struct { 63 62 Pattern string 64 63 CaseSensitive bool 65 64 FileName bool 66 65 } 67 66 68 - func (q *SubstringQuery) String() string { 67 + func (q *Substring) String() string { 69 68 s := "" 70 69 71 70 t := "sub" ··· 80 79 return s 81 80 } 82 81 83 - // OrQuery is matched when any of its children is matched. 84 - type OrQuery struct { 82 + // Or is matched when any of its children is matched. 83 + type Or struct { 85 84 Children []Query 86 85 } 87 86 88 - func (q *OrQuery) String() string { 87 + func (q *Or) String() string { 89 88 var sub []string 90 89 for _, ch := range q.Children { 91 90 sub = append(sub, ch.String()) ··· 93 92 return fmt.Sprintf("(or %s)", strings.Join(sub, " ")) 94 93 } 95 94 96 - // NotQuery inverts the meaning of its child. 97 - type NotQuery struct { 95 + // Not inverts the meaning of its child. 96 + type Not struct { 98 97 Child Query 99 98 } 100 99 101 - func (q *NotQuery) String() string { 100 + func (q *Not) String() string { 102 101 return fmt.Sprintf("(not %s)", q.Child) 103 102 } 104 103 105 - // AndQuery is matched when all its children are. 106 - type AndQuery struct { 104 + // And is matched when all its children are. 105 + type And struct { 107 106 Children []Query 108 107 } 109 108 110 - func (q *AndQuery) String() string { 109 + func (q *And) String() string { 111 110 var sub []string 112 111 for _, ch := range q.Children { 113 112 sub = append(sub, ch.String()) ··· 115 114 return fmt.Sprintf("(and %s)", strings.Join(sub, " ")) 116 115 } 117 116 118 - // BranchQuery limits search to a specific branch. 119 - type BranchQuery struct { 117 + // Branch limits search to a specific branch. 118 + type Branch struct { 120 119 Name string 121 120 } 122 121 123 - func (q *BranchQuery) String() string { 122 + func (q *Branch) String() string { 124 123 return fmt.Sprintf("branch:%q", q.Name) 125 124 } 126 125 127 126 func queryChildren(q Query) []Query { 128 127 switch s := q.(type) { 129 - case *AndQuery: 128 + case *And: 130 129 return s.Children 131 - case *OrQuery: 130 + case *Or: 132 131 return s.Children 133 132 } 134 133 return nil ··· 157 156 // (and (and x y) z) => (and x y z) , the same for "or" 158 157 func flatten(q Query) (Query, bool) { 159 158 switch s := q.(type) { 160 - case *AndQuery: 159 + case *And: 161 160 if len(s.Children) == 1 { 162 161 return s.Children[0], true 163 162 } 164 163 flatChildren, changed := flattenAndOr(s.Children, s) 165 - return &AndQuery{flatChildren}, changed 166 - case *OrQuery: 164 + return &And{flatChildren}, changed 165 + case *Or: 167 166 if len(s.Children) == 1 { 168 167 return s.Children[0], true 169 168 } 170 169 flatChildren, changed := flattenAndOr(s.Children, s) 171 - return &OrQuery{flatChildren}, changed 170 + return &Or{flatChildren}, changed 172 171 default: 173 172 return q, false 174 173 } ··· 182 181 return neg 183 182 } 184 183 185 - func constQuery(c bool) Query { 186 - if c { 187 - return &TrueQuery{} 188 - } 189 - return &FalseQuery{} 190 - } 191 - 192 - func isConst(q Query) (bool, bool) { 193 - if _, ok := q.(*TrueQuery); ok { 194 - return true, true 195 - } 196 - if _, ok := q.(*FalseQuery); ok { 197 - return false, true 198 - } 199 - return false, false 200 - } 201 - 202 184 func invertConst(q Query) Query { 203 - c, ok := isConst(q) 185 + c, ok := q.(*Const) 204 186 if ok { 205 - return constQuery(!c) 187 + return &Const{!c.Value} 206 188 } 207 189 return q 208 190 } 209 191 210 192 func evalAndOrConstants(q Query, children []Query) Query { 211 - _, isAnd := q.(*AndQuery) 193 + _, isAnd := q.(*And) 212 194 213 195 children = mapQueryList(children, evalConstants) 214 196 215 197 newCH := children[:0] 216 198 for _, ch := range children { 217 - c, ok := isConst(ch) 199 + c, ok := ch.(*Const) 218 200 if ok { 219 - if c == isAnd { 201 + if c.Value == isAnd { 220 202 continue 221 203 } else { 222 204 return ch ··· 225 207 newCH = append(newCH, ch) 226 208 } 227 209 if len(newCH) == 0 { 228 - return constQuery(isAnd) 210 + return &Const{isAnd} 229 211 } 230 212 if isAnd { 231 - return &AndQuery{newCH} 213 + return &And{newCH} 232 214 } 233 - return &OrQuery{newCH} 215 + return &Or{newCH} 234 216 } 235 217 236 218 func evalConstants(q Query) Query { 237 219 switch s := q.(type) { 238 - case *AndQuery: 220 + case *And: 239 221 return evalAndOrConstants(q, s.Children) 240 - case *OrQuery: 222 + case *Or: 241 223 return evalAndOrConstants(q, s.Children) 242 - case *NotQuery: 224 + case *Not: 243 225 ch := evalConstants(s.Child) 244 - if _, ok := isConst(ch); ok { 226 + if _, ok := ch.(*Const); ok { 245 227 return invertConst(ch) 246 228 } 247 - return &NotQuery{ch} 229 + return &Not{ch} 248 230 } 249 231 return q 250 232 } 251 233 252 - func simplify(q Query) Query { 234 + func Simplify(q Query) Query { 253 235 q = evalConstants(q) 254 236 for { 255 237 var changed bool ··· 262 244 return q 263 245 } 264 246 265 - // mapQueryList runs f over the q. 266 - func mapQuery(q Query, f func(q Query) Query) Query { 247 + // Map runs f over the q. 248 + func Map(q Query, f func(q Query) Query) Query { 267 249 switch s := q.(type) { 268 - case *AndQuery: 269 - return &AndQuery{Children: mapQueryList(s.Children, f)} 270 - case *OrQuery: 271 - return &OrQuery{Children: mapQueryList(s.Children, f)} 272 - case *NotQuery: 273 - return &NotQuery{Child: f(s.Child)} 250 + case *And: 251 + return &And{Children: mapQueryList(s.Children, f)} 252 + case *Or: 253 + return &Or{Children: mapQueryList(s.Children, f)} 254 + case *Not: 255 + return &Not{Child: f(s.Child)} 274 256 } 275 257 return f(q) 276 258 }
+26
query/bits.go
··· 1 + // Copyright 2016 Google Inc. All rights reserved. 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package query 16 + 17 + func toLower(in []byte) []byte { 18 + out := make([]byte, len(in)) 19 + for i, c := range in { 20 + if c >= 'A' && c <= 'Z' { 21 + c = c - 'A' + 'a' 22 + } 23 + out[i] = c 24 + } 25 + return out 26 + }
+82
query/parse_test.go
··· 1 + // Copyright 2016 Google Inc. All rights reserved. 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package query 16 + 17 + import ( 18 + "reflect" 19 + "regexp/syntax" 20 + "testing" 21 + ) 22 + 23 + func mustParseRE(s string) *syntax.Regexp { 24 + r, err := syntax.Parse(s, 0) 25 + if err != nil { 26 + panic(err) 27 + } 28 + 29 + return r 30 + } 31 + 32 + func TestParseQuery(t *testing.T) { 33 + type testcase struct { 34 + in string 35 + out Query 36 + hasErr bool 37 + } 38 + 39 + for _, c := range []testcase{ 40 + {"sub-pixel", &Substring{Pattern: "sub-pixel"}, false}, 41 + {"abc", &Substring{Pattern: "abc"}, false}, 42 + {"\"abc bcd\"", &Substring{Pattern: "abc bcd"}, false}, 43 + {"abc bcd", &And{[]Query{ 44 + &Substring{Pattern: "abc"}, 45 + &Substring{Pattern: "bcd"}, 46 + }}, false}, 47 + {"-abc", &Not{&Substring{Pattern: "abc"}}, false}, 48 + {"regex:a.b", nil, true}, 49 + 50 + {"abccase:yes", &Substring{Pattern: "abccase:yes"}, false}, 51 + {"file:abc", &Substring{Pattern: "abc", FileName: true}, false}, 52 + {"branch:pqr", &Branch{Name: "pqr"}, false}, 53 + 54 + {"file:helpers.go byte", &And{[]Query{ 55 + &Substring{Pattern: "helpers.go", FileName: true}, 56 + &Substring{Pattern: "byte"}, 57 + }}, false}, 58 + 59 + {"regex:abc[p-q]", &Regexp{mustParseRE("abc[p-q]")}, false}, 60 + {"repo:go", &Repo{"go"}, false}, 61 + 62 + // case 63 + {"abc case:yes", &Substring{Pattern: "abc", CaseSensitive: true}, false}, 64 + {"abc case:auto", &Substring{Pattern: "abc", CaseSensitive: false}, false}, 65 + {"ABC case:auto", &Substring{Pattern: "ABC", CaseSensitive: true}, false}, 66 + {"ABC case:\"auto\"", &Substring{Pattern: "ABC", CaseSensitive: true}, false}, 67 + // errors. 68 + {"\"abc", nil, true}, 69 + {"\"a\\", nil, true}, 70 + {"case:foo", nil, true}, 71 + {"", nil, true}, 72 + } { 73 + q, err := Parse(c.in) 74 + if c.hasErr != (err != nil) { 75 + t.Errorf("Parse(%s): error %v, value %v", c.in, err, q) 76 + } else if q != nil { 77 + if !reflect.DeepEqual(q, c.out) { 78 + t.Errorf("Parse(%s): got %v want %v", c.in, q, c.out) 79 + } 80 + } 81 + } 82 + }
+79
query/query_test.go
··· 1 + // Copyright 2016 Google Inc. All rights reserved. 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package query 16 + 17 + import ( 18 + "log" 19 + "reflect" 20 + "testing" 21 + ) 22 + 23 + var _ = log.Println 24 + 25 + func TestQueryString(t *testing.T) { 26 + q := &Or{[]Query{ 27 + &And{[]Query{ 28 + &Substring{Pattern: "hoi"}, 29 + &Not{&Substring{Pattern: "hai"}}, 30 + }}}} 31 + got := q.String() 32 + want := `(or (and substr:"hoi" (not substr:"hai")))` 33 + 34 + if got != want { 35 + t.Errorf("got %s, want %s", got, want) 36 + } 37 + } 38 + 39 + func TestSimplify(t *testing.T) { 40 + type testcase struct { 41 + in Query 42 + want Query 43 + } 44 + 45 + cases := []testcase{ 46 + { 47 + in: &Or{[]Query{ 48 + &Or{[]Query{ 49 + &And{[]Query{ 50 + &Substring{Pattern: "hoi"}, 51 + &Not{&Substring{Pattern: "hai"}}, 52 + }}, 53 + &Or{[]Query{ 54 + &Substring{Pattern: "zip"}, 55 + &Substring{Pattern: "zap"}, 56 + }}, 57 + }}}}, 58 + want: &Or{[]Query{ 59 + &And{[]Query{ 60 + &Substring{Pattern: "hoi"}, 61 + &Not{&Substring{Pattern: "hai"}}, 62 + }}, 63 + &Substring{Pattern: "zip"}, 64 + &Substring{Pattern: "zap"}}, 65 + }}, 66 + {in: &And{}, want: &Const{true}}, 67 + {in: &Or{}, want: &Const{false}}, 68 + {in: &And{[]Query{&Const{true}, &Const{false}}}, want: &Const{false}}, 69 + {in: &Or{[]Query{&Const{false}, &Const{true}}}, want: &Const{true}}, 70 + {in: &Not{&Const{true}}, want: &Const{false}}, 71 + } 72 + 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 + } 78 + } 79 + }
+84
query/regexp.go
··· 1 + // Copyright 2016 Google Inc. All rights reserved. 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package query 16 + 17 + import ( 18 + "log" 19 + "regexp/syntax" 20 + ) 21 + 22 + var _ = log.Println 23 + 24 + func LowerRegexp(r *syntax.Regexp) *syntax.Regexp { 25 + newRE := *r 26 + switch r.Op { 27 + case syntax.OpLiteral, syntax.OpCharClass: 28 + for i, r := range newRE.Rune { 29 + if r >= 'A' && r <= 'Z' { 30 + newRE.Rune[i] = r + 'a' - 'A' 31 + } 32 + } 33 + default: 34 + for i, s := range newRE.Sub { 35 + newRE.Sub[i] = LowerRegexp(s) 36 + } 37 + } 38 + 39 + return &newRE 40 + } 41 + 42 + func RegexpToQuery(r *syntax.Regexp) Query { 43 + q := regexpToQueryRecursive(r) 44 + q = Simplify(q) 45 + return q 46 + } 47 + 48 + // regexpToQuery tries to distill a substring search query that 49 + // matches a superset of the regexp. 50 + func regexpToQueryRecursive(r *syntax.Regexp) Query { 51 + // TODO - we could perhaps transform Begin/EndText in '\n'? 52 + // TODO - we could perhaps transform CharClass in (OrQuery ) 53 + // if there are just a few runes, and part of a OpConcat? 54 + switch r.Op { 55 + case syntax.OpLiteral: 56 + s := string(r.Rune) 57 + if len(s) >= ngramSize { 58 + return &Substring{Pattern: s} 59 + } 60 + case syntax.OpCapture: 61 + return regexpToQueryRecursive(r.Sub[0]) 62 + 63 + case syntax.OpPlus: 64 + return regexpToQueryRecursive(r.Sub[0]) 65 + 66 + case syntax.OpRepeat: 67 + if r.Min >= 1 { 68 + return regexpToQueryRecursive(r.Sub[0]) 69 + } 70 + 71 + case syntax.OpConcat, syntax.OpAlternate: 72 + var qs []Query 73 + for _, sr := range r.Sub { 74 + if sq := regexpToQueryRecursive(sr); sq != nil { 75 + qs = append(qs, sq) 76 + } 77 + } 78 + if r.Op == syntax.OpConcat { 79 + return &And{qs} 80 + } 81 + return &Or{qs} 82 + } 83 + return &Const{true} 84 + }
-79
query_test.go
··· 1 - // Copyright 2016 Google Inc. All rights reserved. 2 - // 3 - // Licensed under the Apache License, Version 2.0 (the "License"); 4 - // you may not use this file except in compliance with the License. 5 - // You may obtain a copy of the License at 6 - // 7 - // http://www.apache.org/licenses/LICENSE-2.0 8 - // 9 - // Unless required by applicable law or agreed to in writing, software 10 - // distributed under the License is distributed on an "AS IS" BASIS, 11 - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 - // See the License for the specific language governing permissions and 13 - // limitations under the License. 14 - 15 - package zoekt 16 - 17 - import ( 18 - "log" 19 - "reflect" 20 - "testing" 21 - ) 22 - 23 - var _ = log.Println 24 - 25 - func TestQueryString(t *testing.T) { 26 - q := &OrQuery{[]Query{ 27 - &AndQuery{[]Query{ 28 - &SubstringQuery{Pattern: "hoi"}, 29 - &NotQuery{&SubstringQuery{Pattern: "hai"}}, 30 - }}}} 31 - got := q.String() 32 - want := `(or (and substr:"hoi" (not substr:"hai")))` 33 - 34 - if got != want { 35 - t.Errorf("got %s, want %s", got, want) 36 - } 37 - } 38 - 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 - }}, 63 - &SubstringQuery{Pattern: "zip"}, 64 - &SubstringQuery{Pattern: "zap"}}, 65 - }}, 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 - } 72 - 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 - } 78 - } 79 - }
+3 -1
read.go
··· 22 22 "os" 23 23 "path/filepath" 24 24 "time" 25 + 26 + "github.com/google/zoekt/query" 25 27 ) 26 28 27 29 var _ = log.Println ··· 208 210 return nil 209 211 } 210 212 211 - func (ss *shardedSearcher) Search(pat Query) (*SearchResult, error) { 213 + func (ss *shardedSearcher) Search(pat query.Query) (*SearchResult, error) { 212 214 start := time.Now() 213 215 type res struct { 214 216 sr *SearchResult
-70
regexp.go
··· 1 - package zoekt 2 - 3 - import ( 4 - "log" 5 - "regexp/syntax" 6 - ) 7 - 8 - var _ = log.Println 9 - 10 - func lowerRegexp(r *syntax.Regexp) *syntax.Regexp { 11 - newRE := *r 12 - switch r.Op { 13 - case syntax.OpLiteral, syntax.OpCharClass: 14 - for i, r := range newRE.Rune { 15 - if r >= 'A' && r <= 'Z' { 16 - newRE.Rune[i] = r + 'a' - 'A' 17 - } 18 - } 19 - default: 20 - for i, s := range newRE.Sub { 21 - newRE.Sub[i] = lowerRegexp(s) 22 - } 23 - } 24 - 25 - return &newRE 26 - } 27 - 28 - func regexpToQuery(r *syntax.Regexp) Query { 29 - q := regexpToQueryRecursive(r) 30 - q = simplify(q) 31 - return q 32 - } 33 - 34 - // regexpToQuery tries to distill a substring search query that 35 - // matches a superset of the regexp. 36 - func regexpToQueryRecursive(r *syntax.Regexp) Query { 37 - // TODO - we could perhaps transform Begin/EndText in '\n'? 38 - // TODO - we could perhaps transform CharClass in (OrQuery ) 39 - // if there are just a few runes, and part of a OpConcat? 40 - switch r.Op { 41 - case syntax.OpLiteral: 42 - s := string(r.Rune) 43 - if len(s) >= ngramSize { 44 - return &SubstringQuery{Pattern: s} 45 - } 46 - case syntax.OpCapture: 47 - return regexpToQuery(r.Sub[0]) 48 - 49 - case syntax.OpPlus: 50 - return regexpToQuery(r.Sub[0]) 51 - 52 - case syntax.OpRepeat: 53 - if r.Min >= 1 { 54 - return regexpToQuery(r.Sub[0]) 55 - } 56 - 57 - case syntax.OpConcat, syntax.OpAlternate: 58 - var qs []Query 59 - for _, sr := range r.Sub { 60 - if sq := regexpToQuery(sr); sq != nil { 61 - qs = append(qs, sq) 62 - } 63 - } 64 - if r.Op == syntax.OpConcat { 65 - return &AndQuery{qs} 66 - } 67 - return &OrQuery{qs} 68 - } 69 - return &TrueQuery{} 70 - }
+28 -14
regexp_test.go query/regexp_test.go
··· 1 - package zoekt 1 + // Copyright 2016 Google Inc. All rights reserved. 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package query 2 16 3 17 import ( 4 18 "log" ··· 44 58 } 45 59 46 60 cases := []testcase{ 47 - {"(foo|)bar", &SubstringQuery{Pattern: "bar"}}, 48 - {"(foo|)", &TrueQuery{}}, 49 - {"(foo|bar)baz.*bla", &AndQuery{[]Query{ 50 - &OrQuery{[]Query{ 51 - &SubstringQuery{Pattern: "foo"}, 52 - &SubstringQuery{Pattern: "bar"}, 61 + {"(foo|)bar", &Substring{Pattern: "bar"}}, 62 + {"(foo|)", &Const{true}}, 63 + {"(foo|bar)baz.*bla", &And{[]Query{ 64 + &Or{[]Query{ 65 + &Substring{Pattern: "foo"}, 66 + &Substring{Pattern: "bar"}, 53 67 }}, 54 - &SubstringQuery{Pattern: "baz"}, 55 - &SubstringQuery{Pattern: "bla"}, 68 + &Substring{Pattern: "baz"}, 69 + &Substring{Pattern: "bla"}, 56 70 }}}, 57 71 {"^[a-z](People)+barrabas$", 58 - &AndQuery{[]Query{ 59 - &SubstringQuery{Pattern: "People"}, 60 - &SubstringQuery{Pattern: "barrabas"}, 72 + &And{[]Query{ 73 + &Substring{Pattern: "People"}, 74 + &Substring{Pattern: "barrabas"}, 61 75 }}}, 62 76 } 63 77 ··· 68 82 continue 69 83 } 70 84 71 - got := regexpToQuery(r) 85 + got := RegexpToQuery(r) 72 86 if !reflect.DeepEqual(c.want, got) { 73 87 t.Errorf("regexpToQuery(%q): got %v, want %v", c.in, got, c.want) 74 88 } ··· 78 92 func TestLowerRegexp(t *testing.T) { 79 93 in := "[a-zA-Z]fooBAR" 80 94 re := mustParseRE(in) 81 - got := lowerRegexp(re) 95 + got := LowerRegexp(re) 82 96 want := "[a-za-z]foobar" 83 97 if got.String() != want { 84 98 t.Errorf("got %s, want %s", got, want)