Skip to content

Commit 7420d59

Browse files
authored
fix: classifier last token sometimes fail to capture the right values (#2434)
1 parent 2292bd7 commit 7420d59

File tree

4 files changed

+63
-5
lines changed

4 files changed

+63
-5
lines changed

server/aws-lsp-codewhisperer/src/language-server/inline-completion/auto-trigger/autoTrigger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Logging } from '@aws/language-server-runtimes/server-interface'
33
import { FileContext } from '../../../shared/codeWhispererService'
44
import typedCoefficients = require('./coefficients.json')
55
import { TextDocumentContentChangeEvent } from 'vscode-languageserver-textdocument'
6+
import { lastTokenFromString } from '../utils/triggerUtils'
67

78
type TypedCoefficients = typeof typedCoefficients
89
type Coefficients = TypedCoefficients & {
@@ -223,8 +224,7 @@ export const autoTrigger = (
223224
classifierThreshold: TRIGGER_THRESHOLD,
224225
}
225226
}
226-
const tokens = leftContextAtCurrentLine.trim().split(' ')
227-
const lastToken = tokens[tokens.length - 1]
227+
const lastToken = lastTokenFromString(fileContext.leftFileContent)
228228

229229
const keyword = lastToken?.length > 1 ? lastToken : ''
230230

server/aws-lsp-codewhisperer/src/language-server/inline-completion/auto-trigger/editPredictionAutoTrigger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { EditPredictionConfigManager } from './editPredictionConfig'
1010
import { CodeWhispererSupplementalContext } from '../../../shared/models/model'
1111
import { UserTriggerDecision } from '../session/sessionManager'
1212
import { Logging } from '@aws/language-server-runtimes/server-interface'
13+
import { lastTokenFromString } from '../utils/triggerUtils'
1314

1415
// The sigmoid function to clamp the auto-trigger result to the (0, 1) range
1516
const sigmoid = (x: number) => {
@@ -360,8 +361,7 @@ ${params.recentEdits.supplementalContextItems.map(it => it.content)}`)
360361
const lang = params.fileContext.programmingLanguage
361362

362363
// 7. Keywords
363-
const tokens = params.fileContext.leftContextAtCurLine.trim().split(' ') // split(' ') Not strict enough?
364-
const lastToken = tokens[tokens.length - 1]
364+
const lastToken = lastTokenFromString(params.fileContext.leftFileContent)
365365

366366
// 8. User AR for last 5
367367
// Cold start we assume 0.3 for AR

server/aws-lsp-codewhisperer/src/language-server/inline-completion/utils/triggerUtils.test.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as assert from 'assert'
22
import * as sinon from 'sinon'
3-
import { shouldTriggerEdits, NepTrigger, isDocumentChangedFromNewLine } from './triggerUtils'
3+
import { shouldTriggerEdits, NepTrigger, isDocumentChangedFromNewLine, lastTokenFromString } from './triggerUtils'
44
import { SessionManager } from '../session/sessionManager'
55
import { CursorTracker } from '../tracker/cursorTracker'
66
import { RecentEditTracker } from '../tracker/codeEditTracker'
@@ -45,6 +45,50 @@ describe('triggerUtils', () => {
4545
sinon.restore()
4646
})
4747

48+
describe('lastTokenFromString', function () {
49+
interface TestCase {
50+
input: string
51+
expected: string
52+
}
53+
54+
const cases: TestCase[] = [
55+
{
56+
input: `line=str`,
57+
expected: `str`,
58+
},
59+
{
60+
input: `public class Main `,
61+
expected: `Main`,
62+
},
63+
{
64+
input: `const foo = 5`,
65+
expected: `5`,
66+
},
67+
{
68+
input: `const fooString = 'foo'`,
69+
expected: `foo`,
70+
},
71+
{
72+
input: `main(`,
73+
expected: `main`,
74+
},
75+
{
76+
input: `public class Main {
77+
// print foo
78+
`,
79+
expected: `foo`,
80+
},
81+
]
82+
83+
for (let i = 0; i < cases.length; i++) {
84+
const c = cases[i]
85+
it(`case ${i}`, function () {
86+
const actual = lastTokenFromString(c.input)
87+
assert.strictEqual(actual, c.expected)
88+
})
89+
}
90+
})
91+
4892
describe('isDocumentChangedFromNewLine', function () {
4993
interface TestCase {
5094
input: string

server/aws-lsp-codewhisperer/src/language-server/inline-completion/utils/triggerUtils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,17 @@ export function inferTriggerChar(
115115
export function isDocumentChangedFromNewLine(s: string) {
116116
return /^\n[\s\t]+$/.test(s)
117117
}
118+
119+
// TODO: Should refine the logic
120+
export function lastTokenFromString(str: string): string {
121+
const tokens = str.trim().split(/\s+/)
122+
if (tokens.length === 0) {
123+
return ''
124+
}
125+
126+
// This step can filter out most naive case however doesnt work for `line=str` such style without empty space
127+
const candidate = tokens[tokens.length - 1]
128+
// Only run regex against a small portion of string instead of the entire str
129+
const finalCandate = candidate.match(/\w+/g) || []
130+
return finalCandate.at(-1) ?? ''
131+
}

0 commit comments

Comments
 (0)