-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(agent): extract calculateReplaceRange and add unit test. (#764)
* refactor(agent): extract calculateReplaceRange. * test(agent): add unit test for calculateReplaceRangeByBracketStack.
- Loading branch information
Showing
5 changed files
with
259 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
213 changes: 213 additions & 0 deletions
213
clients/tabby-agent/src/postprocess/calculateReplaceRangeByBracketStack.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
import { expect } from "chai"; | ||
import { documentContext, inline } from "./testUtils"; | ||
import { calculateReplaceRangeByBracketStack } from "./calculateReplaceRangeByBracketStack"; | ||
|
||
describe("postprocess", () => { | ||
describe("calculateReplaceRangeByBracketStack", () => { | ||
it("should handle auto closing quotes", () => { | ||
const context = { | ||
...documentContext` | ||
const hello = "║" | ||
`, | ||
language: "typescript", | ||
}; | ||
const response = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├hello";┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position, | ||
}, | ||
}, | ||
], | ||
}; | ||
const expected = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├hello";┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position + 1, | ||
}, | ||
}, | ||
], | ||
}; | ||
expect(calculateReplaceRangeByBracketStack(response, context)).to.deep.equal(expected); | ||
}); | ||
|
||
it("should handle auto closing quotes", () => { | ||
const context = { | ||
...documentContext` | ||
let htmlMarkup = \`║\` | ||
`, | ||
language: "typescript", | ||
}; | ||
const response = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├<h1>\${message}</h1>\`;┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position, | ||
}, | ||
}, | ||
], | ||
}; | ||
const expected = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├<h1>\${message}</h1>\`;┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position + 1, | ||
}, | ||
}, | ||
], | ||
}; | ||
expect(calculateReplaceRangeByBracketStack(response, context)).to.deep.equal(expected); | ||
}); | ||
|
||
it("should handle multiple auto closing brackets", () => { | ||
const context = { | ||
...documentContext` | ||
process.on('data', (data) => {║}) | ||
`, | ||
language: "typescript", | ||
}; | ||
const response = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├ | ||
console.log(data); | ||
});┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position, | ||
}, | ||
}, | ||
], | ||
}; | ||
const expected = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├ | ||
console.log(data); | ||
});┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position + 2, | ||
}, | ||
}, | ||
], | ||
}; | ||
expect(calculateReplaceRangeByBracketStack(response, context)).to.deep.equal(expected); | ||
}); | ||
|
||
it("should handle multiple auto closing brackets", () => { | ||
const context = { | ||
...documentContext` | ||
let mat: number[][][] = [[[║]]] | ||
`, | ||
language: "typescript", | ||
}; | ||
const response = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├1, 2], [3, 4]], [[5, 6], [7, 8]]];┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position, | ||
}, | ||
}, | ||
], | ||
}; | ||
const expected = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├1, 2], [3, 4]], [[5, 6], [7, 8]]];┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position + 3, | ||
}, | ||
}, | ||
], | ||
}; | ||
expect(calculateReplaceRangeByBracketStack(response, context)).to.deep.equal(expected); | ||
}); | ||
}); | ||
|
||
describe("calculateReplaceRangeByBracketStack: bad cases", () => { | ||
const context = { | ||
...documentContext` | ||
function clamp(n: number, max: number, min: number): number { | ||
return Math.max(Math.min(║); | ||
} | ||
`, | ||
language: "typescript", | ||
}; | ||
const response = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├n, max), min┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position, | ||
}, | ||
}, | ||
], | ||
}; | ||
const expected = { | ||
id: "", | ||
choices: [ | ||
{ | ||
index: 0, | ||
text: inline` | ||
├n, max), min┤ | ||
`, | ||
replaceRange: { | ||
start: context.position, | ||
end: context.position, | ||
}, | ||
}, | ||
], | ||
}; | ||
expect(calculateReplaceRangeByBracketStack(response, context)).not.to.deep.equal(expected); | ||
}); | ||
}); |
29 changes: 29 additions & 0 deletions
29
clients/tabby-agent/src/postprocess/calculateReplaceRangeByBracketStack.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { CompletionContext, CompletionResponse } from "../Agent"; | ||
import { isBlank, findUnpairedAutoClosingChars } from "../utils"; | ||
import { logger } from "./base"; | ||
|
||
export function calculateReplaceRangeByBracketStack( | ||
response: CompletionResponse, | ||
context: CompletionContext, | ||
): CompletionResponse { | ||
const { suffixLines } = context; | ||
const suffixText = suffixLines[0]?.trimEnd() || ""; | ||
if (isBlank(suffixText)) { | ||
return response; | ||
} | ||
for (const choice of response.choices) { | ||
const completionText = choice.text.slice(context.position - choice.replaceRange.start); | ||
const unpaired = findUnpairedAutoClosingChars(completionText); | ||
if (isBlank(unpaired)) { | ||
continue; | ||
} | ||
if (suffixText.startsWith(unpaired)) { | ||
choice.replaceRange.end = context.position + unpaired.length; | ||
logger.trace({ context, completion: choice.text, range: choice.replaceRange, unpaired }, "Adjust replace range"); | ||
} else if (unpaired.startsWith(suffixText)) { | ||
choice.replaceRange.end = context.position + suffixText.length; | ||
logger.trace({ context, completion: choice.text, range: choice.replaceRange, unpaired }, "Adjust replace range"); | ||
} | ||
} | ||
return response; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
function clamp(n: number, max: number, min: number): number { | ||
return Math.max(Math.min(⏩⏭n, max), min⏮⏪); | ||
} |