From 570757e20b467174defc40c67ac097cf81a72082 Mon Sep 17 00:00:00 2001 From: Matthew Manela Date: Mon, 29 Apr 2024 14:23:08 -0400 Subject: [PATCH] Honor regex flags for case-sensitivity (#767) * Honor regex flags for case-sensitivity * change * add test * pr comment --- .vscode/launch.json | 14 +++++++++++++ eval.go | 3 ++- eval_test.go | 49 +++++++++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..dffa3c19e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Process (from list)", + "type": "go", + "request": "attach", + "mode": "local" + }, + ] +} \ No newline at end of file diff --git a/eval.go b/eval.go index 7cbd3658f..cc0e61f27 100644 --- a/eval.go +++ b/eval.go @@ -641,7 +641,8 @@ func (d *indexData) regexpToMatchTreeRecursive(r *syntax.Regexp, minTextSize int case syntax.OpLiteral: s := string(r.Rune) if len(s) >= minTextSize { - mt, err := d.newSubstringMatchTree(&query.Substring{Pattern: s, FileName: fileName, CaseSensitive: caseSensitive}) + ignoreCase := syntax.FoldCase == (r.Flags & syntax.FoldCase) + mt, err := d.newSubstringMatchTree(&query.Substring{Pattern: s, FileName: fileName, CaseSensitive: !ignoreCase && caseSensitive}) return mt, true, !strings.Contains(s, "\n"), err } case syntax.OpCapture: diff --git a/eval_test.go b/eval_test.go index aeff6c27e..32cefdea0 100644 --- a/eval_test.go +++ b/eval_test.go @@ -59,24 +59,35 @@ func printRegexp(t *testing.T, r *syntax.Regexp, lvl int) { } } +func caseSensitiveSubstrMT(pattern string) matchTree { + d := &indexData{} + mt, _ := d.newSubstringMatchTree(&query.Substring{ + Pattern: pattern, + CaseSensitive: true, + }) + return mt +} + func substrMT(pattern string) matchTree { d := &indexData{} mt, _ := d.newSubstringMatchTree(&query.Substring{ - Pattern: pattern, + Pattern: pattern, + CaseSensitive: false, }) return mt } func TestRegexpParse(t *testing.T) { type testcase struct { - in string - query matchTree - isEquivalent bool + in string + query matchTree + isEquivalent bool + caseSensitive bool } cases := []testcase{ - {"(foo|)bar", substrMT("bar"), false}, - {"(foo|)", &bruteForceMatchTree{}, false}, + {"(foo|)bar", substrMT("bar"), false, false}, + {"(foo|)", &bruteForceMatchTree{}, false, false}, {"(foo|bar)baz.*bla", &andMatchTree{[]matchTree{ &orMatchTree{[]matchTree{ substrMT("foo"), @@ -84,32 +95,35 @@ func TestRegexpParse(t *testing.T) { }}, substrMT("baz"), substrMT("bla"), - }}, false}, + }}, false, false}, { "^[a-z](People)+barrabas$", &andMatchTree{[]matchTree{ substrMT("People"), substrMT("barrabas"), - }}, false, + }}, false, false, }, - {"foo", substrMT("foo"), true}, - {"^foo", substrMT("foo"), false}, - {"(foo) (bar)", &andMatchTree{[]matchTree{substrMT("foo"), substrMT("bar")}}, false}, + {"foo", substrMT("foo"), true, false}, + {"foo", caseSensitiveSubstrMT("foo"), true, true}, + {"(?i)foo", substrMT("FOO"), true, false}, + {"(?i)foo", substrMT("FOO"), true, true}, + {"^foo", substrMT("foo"), false, false}, + {"(foo) (bar)", &andMatchTree{[]matchTree{substrMT("foo"), substrMT("bar")}}, false, false}, {"(thread|needle|haystack)", &orMatchTree{[]matchTree{ substrMT("thread"), substrMT("needle"), substrMT("haystack"), - }}, true}, + }}, true, false}, {"(foo)(?-s:.)*?(bar)", &andLineMatchTree{andMatchTree{[]matchTree{ substrMT("foo"), substrMT("bar"), - }}}, false}, + }}}, false, false}, {"(foo)(?-s:.)*?[[:space:]](?-s:.)*?(bar)", &andMatchTree{[]matchTree{ substrMT("foo"), substrMT("bar"), - }}, false}, - {"(foo){2,}", substrMT("foo"), false}, - {"(...)(...)", &bruteForceMatchTree{}, false}, + }}, false, false}, + {"(foo){2,}", substrMT("foo"), false, false}, + {"(...)(...)", &bruteForceMatchTree{}, false, false}, } for _, c := range cases { @@ -120,7 +134,8 @@ func TestRegexpParse(t *testing.T) { } d := indexData{} q := query.Regexp{ - Regexp: r, + Regexp: r, + CaseSensitive: c.caseSensitive, } gotQuery, isEq, _, _ := d.regexpToMatchTreeRecursive(q.Regexp, 3, q.FileName, q.CaseSensitive) if !reflect.DeepEqual(c.query, gotQuery) {