Skip to content

Commit 6885e54

Browse files
Merge master into feature/emr
2 parents e7b90c5 + 31493a6 commit 6885e54

File tree

10 files changed

+136
-92
lines changed

10 files changed

+136
-92
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "Automatically pause and resume @workspace indexing when OS CPU load is high"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "Inline completion for more json files, and all yaml files"
4+
}

packages/amazonq/test/unit/codewhisperer/util/commonUtil.test.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
*/
55

66
import assert from 'assert'
7-
import { checkLeftContextKeywordsForJsonAndYaml, getPrefixSuffixOverlap } from 'aws-core-vscode/codewhisperer'
7+
import {
8+
JsonConfigFileNamingConvention,
9+
checkLeftContextKeywordsForJson,
10+
getPrefixSuffixOverlap,
11+
} from 'aws-core-vscode/codewhisperer'
812

913
describe('commonUtil', function () {
1014
describe('getPrefixSuffixOverlap', function () {
@@ -31,29 +35,47 @@ describe('commonUtil', function () {
3135
})
3236
})
3337

34-
describe('checkLeftContextKeywordsForJsonAndYaml', function () {
38+
describe('checkLeftContextKeywordsForJson', function () {
3539
it('Should return true for valid left context keywords', async function () {
3640
assert.strictEqual(
37-
checkLeftContextKeywordsForJsonAndYaml('Create an S3 Bucket named CodeWhisperer', 'json'),
38-
true
39-
)
40-
assert.strictEqual(
41-
checkLeftContextKeywordsForJsonAndYaml('Create an S3 Bucket named CodeWhisperer', 'yaml'),
41+
checkLeftContextKeywordsForJson('foo.json', 'Create an S3 Bucket named CodeWhisperer', 'json'),
4242
true
4343
)
4444
})
4545
it('Should return false for invalid left context keywords', async function () {
4646
assert.strictEqual(
47-
checkLeftContextKeywordsForJsonAndYaml('Create an S3 Bucket named CodeWhisperer in cfn', 'yaml'),
48-
false
49-
)
50-
assert.strictEqual(
51-
checkLeftContextKeywordsForJsonAndYaml(
47+
checkLeftContextKeywordsForJson(
48+
'foo.json',
5249
'Create an S3 Bucket named CodeWhisperer in Cloudformation',
5350
'json'
5451
),
5552
false
5653
)
5754
})
55+
56+
for (const jsonConfigFile of JsonConfigFileNamingConvention) {
57+
it(`should evalute by filename ${jsonConfigFile}`, function () {
58+
assert.strictEqual(checkLeftContextKeywordsForJson(jsonConfigFile, 'foo', 'json'), false)
59+
60+
assert.strictEqual(checkLeftContextKeywordsForJson(jsonConfigFile.toUpperCase(), 'bar', 'json'), false)
61+
62+
assert.strictEqual(checkLeftContextKeywordsForJson(jsonConfigFile.toUpperCase(), 'baz', 'json'), false)
63+
})
64+
65+
const upperCaseFilename = jsonConfigFile.toUpperCase()
66+
it(`should evalute by filename and case insensitive ${upperCaseFilename}`, function () {
67+
assert.strictEqual(checkLeftContextKeywordsForJson(upperCaseFilename, 'foo', 'json'), false)
68+
69+
assert.strictEqual(
70+
checkLeftContextKeywordsForJson(upperCaseFilename.toUpperCase(), 'bar', 'json'),
71+
false
72+
)
73+
74+
assert.strictEqual(
75+
checkLeftContextKeywordsForJson(upperCaseFilename.toUpperCase(), 'baz', 'json'),
76+
false
77+
)
78+
})
79+
}
5880
})
5981
})

packages/amazonq/test/unit/codewhisperer/util/crossFileContextUtil.test.ts

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import assert from 'assert'
77
import * as vscode from 'vscode'
88
import * as sinon from 'sinon'
99
import * as crossFile from 'aws-core-vscode/codewhisperer'
10-
import { createMockTextEditor } from 'aws-core-vscode/test'
10+
import { aStringWithLineCount, createMockTextEditor } from 'aws-core-vscode/test'
1111
import { crossFileContextConfig } from 'aws-core-vscode/codewhisperer'
1212
import {
1313
assertTabCount,
@@ -35,18 +35,18 @@ describe('crossFileContextUtil', function () {
3535
tempFolder = (await createTestWorkspaceFolder()).uri.fsPath
3636
})
3737

38-
it('should fetch 3 chunks and each chunk should contains 10 lines', async function () {
39-
await toTextEditor(sampleFileOf60Lines, 'CrossFile.java', tempFolder, { preview: false })
38+
it('should fetch 3 chunks and each chunk should contains 50 lines', async function () {
39+
await toTextEditor(aStringWithLineCount(200), 'CrossFile.java', tempFolder, { preview: false })
4040
const myCurrentEditor = await toTextEditor('', 'TargetFile.java', tempFolder, {
4141
preview: false,
4242
})
4343
const actual = await crossFile.fetchSupplementalContextForSrc(myCurrentEditor, fakeCancellationToken)
4444
assert.ok(actual)
4545
assert.ok(actual.supplementalContextItems.length === 3)
4646

47-
assert.strictEqual(actual.supplementalContextItems[0].content.split('\n').length, 10)
48-
assert.strictEqual(actual.supplementalContextItems[1].content.split('\n').length, 10)
49-
assert.strictEqual(actual.supplementalContextItems[2].content.split('\n').length, 10)
47+
assert.strictEqual(actual.supplementalContextItems[0].content.split('\n').length, 50)
48+
assert.strictEqual(actual.supplementalContextItems[1].content.split('\n').length, 50)
49+
assert.strictEqual(actual.supplementalContextItems[2].content.split('\n').length, 50)
5050
})
5151
})
5252

@@ -250,73 +250,59 @@ describe('crossFileContextUtil', function () {
250250
assert.strictEqual(chunks[1].content, 'line_6\nline_7')
251251
})
252252

253-
it('codewhisperer crossfile config should use 10 lines', async function () {
253+
it('codewhisperer crossfile config should use 50 lines', async function () {
254254
const filePath = path.join(tempFolder, 'file.txt')
255-
await toFile(sampleFileOf60Lines, filePath)
255+
await toFile(aStringWithLineCount(210), filePath)
256256

257257
const chunks = await crossFile.splitFileToChunks(filePath, crossFileContextConfig.numberOfLinesEachChunk)
258-
assert.strictEqual(chunks.length, 6)
258+
259+
// (210 / 50) + 1
260+
assert.strictEqual(chunks.length, 5)
261+
// line0 -> line49
262+
assert.strictEqual(chunks[0].content, aStringWithLineCount(50, 0))
263+
// line50 -> line99
264+
assert.strictEqual(chunks[1].content, aStringWithLineCount(50, 50))
265+
// line100 -> line149
266+
assert.strictEqual(chunks[2].content, aStringWithLineCount(50, 100))
267+
// line150 -> line199
268+
assert.strictEqual(chunks[3].content, aStringWithLineCount(50, 150))
269+
// line 200 -> line209
270+
assert.strictEqual(chunks[4].content, aStringWithLineCount(10, 200))
271+
})
272+
273+
it('linkChunks should add another chunk which will link to the first chunk and chunk.nextContent should reflect correct value', async function () {
274+
const filePath = path.join(tempFolder, 'file.txt')
275+
await toFile(aStringWithLineCount(210), filePath)
276+
277+
const chunks = await crossFile.splitFileToChunks(filePath, crossFileContextConfig.numberOfLinesEachChunk)
278+
const linkedChunks = crossFile.linkChunks(chunks)
279+
280+
// 210 / 50 + 2
281+
assert.strictEqual(linkedChunks.length, 6)
282+
283+
// 0th
284+
assert.strictEqual(linkedChunks[0].content, aStringWithLineCount(3, 0))
285+
assert.strictEqual(linkedChunks[0].nextContent, aStringWithLineCount(50, 0))
286+
287+
// 1st
288+
assert.strictEqual(linkedChunks[1].content, aStringWithLineCount(50, 0))
289+
assert.strictEqual(linkedChunks[1].nextContent, aStringWithLineCount(50, 50))
290+
291+
// 2nd
292+
assert.strictEqual(linkedChunks[2].content, aStringWithLineCount(50, 50))
293+
assert.strictEqual(linkedChunks[2].nextContent, aStringWithLineCount(50, 100))
294+
295+
// 3rd
296+
assert.strictEqual(linkedChunks[3].content, aStringWithLineCount(50, 100))
297+
assert.strictEqual(linkedChunks[3].nextContent, aStringWithLineCount(50, 150))
298+
299+
// 4th
300+
assert.strictEqual(linkedChunks[4].content, aStringWithLineCount(50, 150))
301+
assert.strictEqual(linkedChunks[4].nextContent, aStringWithLineCount(10, 200))
302+
303+
// 5th
304+
assert.strictEqual(linkedChunks[5].content, aStringWithLineCount(10, 200))
305+
assert.strictEqual(linkedChunks[5].nextContent, aStringWithLineCount(10, 200))
259306
})
260307
})
261308
})
262-
263-
const sampleFileOf60Lines = `import java.util.List;
264-
// we need this comment on purpose because chunk will be trimed right, adding this to avoid trimRight and make assertion easier
265-
/**
266-
*
267-
*
268-
*
269-
*
270-
*
271-
**/
272-
class Main {
273-
public static void main(String[] args) {
274-
Calculator calculator = new Calculator();
275-
calculator.add(1, 2);
276-
calculator.subtract(1, 2);
277-
calculator.multiply(1, 2);
278-
calculator.divide(1, 2);
279-
calculator.remainder(1, 2);
280-
}
281-
}
282-
//
283-
class Calculator {
284-
public Calculator() {
285-
System.out.println("constructor");
286-
}
287-
//
288-
public add(int num1, int num2) {
289-
System.out.println("add");
290-
return num1 + num2;
291-
}
292-
//
293-
public subtract(int num1, int num2) {
294-
System.out.println("subtract");
295-
return num1 - num2;
296-
}
297-
//
298-
public multiply(int num1, int num2) {
299-
System.out.println("multiply");
300-
return num1 * num2;
301-
}
302-
//
303-
public divide(int num1, int num2) {
304-
System.out.println("divide");
305-
return num1 / num2;
306-
}
307-
//
308-
public remainder(int num1, int num2) {
309-
System.out.println("remainder");
310-
return num1 % num2;
311-
}
312-
//
313-
public power(int num1, int num2) {
314-
System.out.println("power");
315-
return (int) Math.pow(num1, num2);
316-
}
317-
//
318-
public squareRoot(int num1) {
319-
System.out.println("squareRoot");
320-
return (int) Math.sqrt(num1);
321-
}
322-
}`

packages/core/src/amazonq/lsp/lspController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export interface Manifest {
6868
}
6969
const manifestUrl = 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json'
7070
// this LSP client in Q extension is only going to work with these LSP server versions
71-
const supportedLspServerVersions = ['0.1.9']
71+
const supportedLspServerVersions = ['0.1.13']
7272

7373
const nodeBinName = process.platform === 'win32' ? 'node.exe' : 'node'
7474
/*
@@ -285,7 +285,7 @@ export class LspController {
285285
const resp: RelevantTextDocument[] = []
286286
chunks?.forEach((chunk) => {
287287
const text = chunk.context ? chunk.context : chunk.content
288-
if (chunk.programmingLanguage) {
288+
if (chunk.programmingLanguage && chunk.programmingLanguage !== 'unknown') {
289289
resp.push({
290290
text: text,
291291
relativeFilePath: chunk.relativePath ? chunk.relativePath : path.basename(chunk.filePath),

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ export const AWSTemplateKeyWords = ['AWSTemplateFormatVersion', 'Resources', 'AW
2222

2323
export const AWSTemplateCaseInsensitiveKeyWords = ['cloudformation', 'cfn', 'template', 'description']
2424

25+
export const JsonConfigFileNamingConvention = new Set([
26+
'app.json',
27+
'appsettings.json',
28+
'bower.json',
29+
'composer.json',
30+
'db.json',
31+
'manifest.json',
32+
'package.json',
33+
'schema.json',
34+
'settings.json',
35+
'tsconfig.json',
36+
'vcpkg.json',
37+
])
38+
2539
export const normalTextChangeRegex = /[A-Za-z0-9]/g
2640

2741
export const autoSuggestionConfig = {
@@ -697,7 +711,7 @@ export const runSecurityScanButtonTitle = 'Run security scan'
697711
export const crossFileContextConfig = {
698712
numberOfChunkToFetch: 60,
699713
topK: 3,
700-
numberOfLinesEachChunk: 10,
714+
numberOfLinesEachChunk: 50,
701715
}
702716

703717
export const utgConfig = {

packages/core/src/codewhisperer/util/commonUtil.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import * as vscode from 'vscode'
77
import * as semver from 'semver'
88
import { isCloud9 } from '../../shared/extensionUtilities'
99
import { getInlineSuggestEnabled } from '../../shared/utilities/editorUtilities'
10-
import { AWSTemplateCaseInsensitiveKeyWords, AWSTemplateKeyWords } from '../models/constants'
10+
import {
11+
AWSTemplateCaseInsensitiveKeyWords,
12+
AWSTemplateKeyWords,
13+
JsonConfigFileNamingConvention,
14+
} from '../models/constants'
1115

1216
export function getLocalDatetime() {
1317
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
@@ -61,11 +65,12 @@ export function getPrefixSuffixOverlap(firstString: string, secondString: string
6165
return secondString.slice(0, i)
6266
}
6367

64-
export function checkLeftContextKeywordsForJsonAndYaml(leftFileContent: string, language: string): boolean {
68+
export function checkLeftContextKeywordsForJson(fileName: string, leftFileContent: string, language: string): boolean {
6569
if (
66-
(language === 'json' || language === 'yaml') &&
70+
language === 'json' &&
6771
!AWSTemplateKeyWords.some((substring) => leftFileContent.includes(substring)) &&
68-
!AWSTemplateCaseInsensitiveKeyWords.some((substring) => leftFileContent.toLowerCase().includes(substring))
72+
!AWSTemplateCaseInsensitiveKeyWords.some((substring) => leftFileContent.toLowerCase().includes(substring)) &&
73+
!JsonConfigFileNamingConvention.has(fileName.toLowerCase())
6974
) {
7075
return true
7176
}

packages/core/src/codewhisperer/util/editorContext.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { fetchSupplementalContext } from './supplementalContext/supplementalCont
1414
import { supplementalContextTimeoutInMs } from '../models/constants'
1515
import { getSelectedCustomization } from './customizationUtil'
1616
import { selectFrom } from '../../shared/utilities/tsUtils'
17-
import { checkLeftContextKeywordsForJsonAndYaml } from './commonUtil'
17+
import { checkLeftContextKeywordsForJson } from './commonUtil'
1818
import { CodeWhispererSupplementalContext } from '../models/model'
1919
import { getOptOutPreference } from '../../shared/telemetry/util'
2020

@@ -39,7 +39,7 @@ export function extractContextForCodeWhisperer(editor: vscode.TextEditor): codew
3939
)
4040
)
4141
let languageName = 'plaintext'
42-
if (!checkLeftContextKeywordsForJsonAndYaml(caretLeftFileContext, editor.document.languageId)) {
42+
if (!checkLeftContextKeywordsForJson(document.fileName, caretLeftFileContext, editor.document.languageId)) {
4343
languageName =
4444
runtimeLanguageContext.normalizeLanguage(editor.document.languageId) ?? editor.document.languageId
4545
}

packages/core/src/codewhisperer/util/supplementalContext/crossFileContextUtil.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ function shouldFetchCrossFileContext(languageId: vscode.TextDocument['languageId
164164
* when a given chunk context passes the match in BM25.
165165
* Special handling is needed for last(its next points to its own) and first chunk
166166
*/
167-
function linkChunks(chunks: Chunk[]) {
167+
export function linkChunks(chunks: Chunk[]) {
168168
const updatedChunks: Chunk[] = []
169169

170170
// This additional chunk is needed to create a next pointer to chunk 0.

packages/core/src/test/codewhisperer/testUtil.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,12 @@ export function createMockDirentFile(fileName: string): Dirent {
207207
dirent.name = fileName
208208
return dirent
209209
}
210+
211+
export function aStringWithLineCount(lineCount: number, start: number = 0): string {
212+
let s = ''
213+
for (let i = start; i < start + lineCount; i++) {
214+
s += `line${i}\n`
215+
}
216+
217+
return s.trimEnd()
218+
}

0 commit comments

Comments
 (0)