Skip to content

Commit a20e112

Browse files
authored
Merge pull request #8830 from uinstinct/ripgrep-regex
fix: regular expressions in ripgrep
1 parent 1b125c3 commit a20e112

File tree

3 files changed

+9
-32
lines changed

3 files changed

+9
-32
lines changed

core/tools/definitions/grepSearch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ export const grepSearchTool: Tool = {
1313
function: {
1414
name: BuiltInToolNames.GrepSearch,
1515
description:
16-
"Performs a regex search over the repository using ripgrep. Will not include results for many build, cache, secrets dirs/files. Output may be truncated, so use targeted queries",
16+
"Performs a regular expression (regex) search over the repository using ripgrep. Will not include results for many build, cache, secrets dirs/files. Output may be truncated, so use targeted queries",
1717
parameters: {
1818
type: "object",
1919
required: ["query"],
2020
properties: {
2121
query: {
2222
type: "string",
2323
description:
24-
"The search query to use. Must be the exact string to be searched or a valid ripgrep expression. Use regex with alternation (e.g., 'word1|word2|word3) or character classes to find multiple potential words in a single search.",
24+
"The regex pattern to search for within file contents. Use regex with alternation (e.g., 'word1|word2|word3') or character classes to find multiple potential words in a single search.",
2525
},
2626
},
2727
},

core/util/regexValidator.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,6 @@ export function prepareQueryForRipgrep(query: string): {
150150
query: string;
151151
warning?: string;
152152
} {
153-
// Check if it looks like a literal search that should be escaped
154-
if (looksLikeLiteralSearch(query)) {
155-
return {
156-
query: escapeLiteralForRegex(query),
157-
warning:
158-
"Query contained special regex characters and was escaped for literal text search",
159-
};
160-
}
161-
162-
// Otherwise validate and sanitize as regex
163153
const validation = validateAndSanitizeRegex(query);
164154

165155
return {

core/util/regexValidator.vitest.ts

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ describe("looksLikeLiteralSearch", () => {
111111
describe("prepareQueryForRipgrep", () => {
112112
it("should escape literal-looking queries", () => {
113113
const result = prepareQueryForRipgrep("hello.world");
114-
expect(result.query).toBe("hello\\.world");
115-
expect(result.warning).toContain("escaped for literal text search");
114+
expect(result.query).toBe("hello.world");
116115
});
117116

118117
it("should sanitize regex patterns", () => {
@@ -130,14 +129,12 @@ describe("prepareQueryForRipgrep", () => {
130129
describe("real-world examples", () => {
131130
it("should escape file patterns", () => {
132131
const result = prepareQueryForRipgrep("*.js");
133-
expect(result.query).toBe("\\*\\.js");
134-
expect(result.warning).toContain("escaped for literal text search");
132+
expect(result.query).toBe("*.js");
135133
});
136134

137135
it("should escape function calls", () => {
138136
const result = prepareQueryForRipgrep("console.log()");
139-
expect(result.query).toBe("console\\.log\\(\\)");
140-
expect(result.warning).toContain("escaped for literal text search");
137+
expect(result.query).toBe("console.log()");
141138
});
142139

143140
it("should not escape proper regex patterns", () => {
@@ -163,8 +160,7 @@ describe("problematic patterns that originally failed", () => {
163160

164161
it("should handle dollar signs in shell patterns", () => {
165162
const result = prepareQueryForRipgrep("$(command)");
166-
expect(result.query).toBe("\\$\\(command\\)");
167-
expect(result.warning).toContain("escaped for literal text search");
163+
expect(result.query).toBe("$(command)");
168164
});
169165

170166
it("should handle escaped dollar signs", () => {
@@ -253,8 +249,7 @@ describe("patterns that should NOT be over-sanitized", () => {
253249
describe("edge cases that could trigger false positives", () => {
254250
it("should not treat mathematical expressions as problematic", () => {
255251
const result = prepareQueryForRipgrep("a + b * c");
256-
expect(result.query).toBe("a \\+ b \\* c"); // Should be escaped as literal
257-
expect(result.warning).toContain("escaped for literal text search");
252+
expect(result.query).toBe("a + b * c"); // Should be escaped as literal
258253
});
259254

260255
it("should not break regex that uses word boundaries", () => {
@@ -271,8 +266,7 @@ describe("patterns that should NOT be over-sanitized", () => {
271266

272267
it("should not treat IPv4 addresses as problematic regex", () => {
273268
const result = prepareQueryForRipgrep("192.168.1.1");
274-
expect(result.query).toBe("192\\.168\\.1\\.1"); // Should be escaped as literal
275-
expect(result.warning).toContain("escaped for literal text search");
269+
expect(result.query).toBe("192.168.1.1"); // Should be escaped as literal
276270
});
277271

278272
it("should not break hex color codes", () => {
@@ -285,8 +279,7 @@ describe("patterns that should NOT be over-sanitized", () => {
285279
describe("patterns that should preserve user intent", () => {
286280
it("should not sanitize intentional regex alternation", () => {
287281
const result = prepareQueryForRipgrep("(foo|bar)");
288-
expect(result.query).toBe("\\(foo\\|bar\\)"); // Should be escaped as literal since unescaped
289-
expect(result.warning).toContain("escaped for literal text search");
282+
expect(result.query).toBe("(foo|bar)"); // Should be escaped as literal since unescaped
290283
});
291284

292285
it("should preserve escaped alternation in regex", () => {
@@ -300,11 +293,5 @@ describe("patterns that should NOT be over-sanitized", () => {
300293
expect(result.query).toBe("name LIKE '%john%'"); // No regex metacharacters here
301294
expect(result.warning).toBeUndefined();
302295
});
303-
304-
it("should not break CSS selectors when used as literal search", () => {
305-
const result = prepareQueryForRipgrep(".class-name > div:nth-child(2)");
306-
expect(result.query).toBe("\\.class-name > div:nth-child\\(2\\)");
307-
expect(result.warning).toContain("escaped for literal text search");
308-
});
309296
});
310297
});

0 commit comments

Comments
 (0)