Skip to content

Commit 8a3251d

Browse files
committed
Merge branch 'main' of https://github.com/continuedev/continue into fix/readFileRange-kotlin-int-overflow
2 parents 5acb0cb + 6e9c43a commit 8a3251d

File tree

76 files changed

+1127
-696
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1127
-696
lines changed

.github/workflows/jetbrains-release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ jobs:
107107
ref: ${{ github.event.release.tag_name }}
108108

109109
- name: Import Apple certificate
110-
uses: apple-actions/import-codesign-certs@v5
110+
uses: apple-actions/import-codesign-certs@v6
111111
with:
112112
keychain: ${{ github.run_id }}
113113
keychain-password: ${{ github.run_id }}

core/edit/searchAndReplace/findSearchMatch.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,25 @@ function trimmedMatch(
5959
return null;
6060
}
6161

62+
/**
63+
* Case-insensitive matching strategy
64+
*/
65+
function caseInsensitiveMatch(
66+
fileContent: string,
67+
searchContent: string,
68+
): BasicMatchResult | null {
69+
const lowerFileContent = fileContent.toLowerCase();
70+
const lowerSearchContent = searchContent.toLowerCase();
71+
const index = lowerFileContent.indexOf(lowerSearchContent);
72+
if (index !== -1) {
73+
return {
74+
startIndex: index,
75+
endIndex: index + searchContent.length,
76+
};
77+
}
78+
return null;
79+
}
80+
6281
/**
6382
* Whitespace-ignored matching strategy
6483
* Removes all whitespace from both content and search, then finds the match
@@ -284,6 +303,7 @@ function findFuzzyMatch(
284303
const matchingStrategies: Array<{ strategy: MatchStrategy; name: string }> = [
285304
{ strategy: exactMatch, name: "exactMatch" },
286305
{ strategy: trimmedMatch, name: "trimmedMatch" },
306+
{ strategy: caseInsensitiveMatch, name: "caseInsensitiveMatch" },
287307
{ strategy: whitespaceIgnoredMatch, name: "whitespaceIgnoredMatch" },
288308
// { strategy: findFuzzyMatch, name: "jaroWinklerFuzzyMatch" },
289309
];

core/edit/searchAndReplace/findSearchMatch.vitest.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,11 @@ describe("findSearchMatch", () => {
109109
const searchContent = "hello";
110110
const result = findSearchMatch(fileContent, searchContent);
111111

112-
// Should not match due to case sensitivity, will fall through to other strategies
113-
expect(result).toBeNull();
112+
expect(result).toEqual({
113+
startIndex: 0,
114+
endIndex: 5,
115+
strategyName: "caseInsensitiveMatch",
116+
});
114117
});
115118
});
116119

@@ -152,6 +155,32 @@ describe("findSearchMatch", () => {
152155
});
153156
});
154157

158+
describe("Case insensitive match strategy fallback", () => {
159+
it("should match when case differs", () => {
160+
const result = findSearchMatch(
161+
"const myVariable = 42;",
162+
"const MYVARIABLE = 42;",
163+
);
164+
expect(result).toEqual({
165+
startIndex: 0,
166+
endIndex: 22,
167+
strategyName: "caseInsensitiveMatch",
168+
});
169+
});
170+
171+
it("should match mixed case in middle of file", () => {
172+
const result = findSearchMatch(
173+
"function HandleClick() {",
174+
"function handleclick() {",
175+
);
176+
expect(result).toEqual({
177+
startIndex: 0,
178+
endIndex: 24,
179+
strategyName: "caseInsensitiveMatch",
180+
});
181+
});
182+
});
183+
155184
describe("Whitespace ignored strategy fallback", () => {
156185
it("should match content with different whitespace formatting", () => {
157186
const fileContent = "function test() {\n return true;\n}";

core/edit/searchAndReplace/findSearchMatches.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,98 @@ line 3 foo`;
113113
});
114114
});
115115

116+
describe("case insensitive match strategy", () => {
117+
it("should find multiple occurrences with different cases", () => {
118+
const content = "const Foo = 'FOO';";
119+
const search = "foo";
120+
const matches = findSearchMatches(content, search);
121+
122+
expect(matches).toHaveLength(2);
123+
expect(matches[0]).toEqual({
124+
startIndex: 6,
125+
endIndex: 9,
126+
strategyName: "caseInsensitiveMatch",
127+
});
128+
expect(matches[1]).toEqual({
129+
startIndex: 13,
130+
endIndex: 16,
131+
strategyName: "caseInsensitiveMatch",
132+
});
133+
});
134+
135+
it("should handle mixed case patterns", () => {
136+
const content = "const MyVariable = 'value';";
137+
const search = "mYvArIaBlE";
138+
const matches = findSearchMatches(content, search);
139+
140+
expect(matches).toHaveLength(1);
141+
expect(matches[0]).toEqual({
142+
startIndex: 6,
143+
endIndex: 16,
144+
strategyName: "caseInsensitiveMatch",
145+
});
146+
});
147+
148+
it("should find multiple matches with varying cases", () => {
149+
const content = "Hello world, HELLO universe, HeLLo there";
150+
const search = "hello";
151+
const matches = findSearchMatches(content, search);
152+
153+
expect(matches).toHaveLength(3);
154+
expect(matches[0]).toEqual({
155+
startIndex: 0,
156+
endIndex: 5,
157+
strategyName: "caseInsensitiveMatch",
158+
});
159+
expect(matches[1]).toEqual({
160+
startIndex: 13,
161+
endIndex: 18,
162+
strategyName: "caseInsensitiveMatch",
163+
});
164+
expect(matches[2]).toEqual({
165+
startIndex: 29,
166+
endIndex: 34,
167+
strategyName: "caseInsensitiveMatch",
168+
});
169+
});
170+
171+
it("should handle multi-line content with case differences", () => {
172+
const content = `function Test() {
173+
return TRUE;
174+
}`;
175+
const search = "test";
176+
const matches = findSearchMatches(content, search);
177+
178+
expect(matches).toHaveLength(1);
179+
expect(matches[0]).toEqual({
180+
startIndex: 9,
181+
endIndex: 13,
182+
strategyName: "caseInsensitiveMatch",
183+
});
184+
});
185+
186+
it("should preserve original content length in match", () => {
187+
const content = "const VARIABLE = 'value';";
188+
const search = "variable";
189+
const matches = findSearchMatches(content, search);
190+
191+
expect(matches).toHaveLength(1);
192+
expect(matches[0].endIndex - matches[0].startIndex).toBe(8);
193+
expect(content.slice(matches[0].startIndex, matches[0].endIndex)).toBe(
194+
"VARIABLE",
195+
);
196+
});
197+
198+
it("should not match when exact and trimmed strategies succeed", () => {
199+
const content = "const foo = 'bar';";
200+
const search = "foo";
201+
const matches = findSearchMatches(content, search);
202+
203+
expect(matches).toHaveLength(1);
204+
expect(matches[0].strategyName).toBe("exactMatch");
205+
});
206+
});
207+
116208
describe("whitespace ignored match strategy", () => {
117209
it("should find matches ignoring internal whitespace", () => {
118210
const content = "const foo = bar;";

0 commit comments

Comments
 (0)