diff --git a/server/src/__tests__/completions.test.ts b/server/src/__tests__/completions.test.ts index b2e23b2d..a5bc501d 100644 --- a/server/src/__tests__/completions.test.ts +++ b/server/src/__tests__/completions.test.ts @@ -404,22 +404,41 @@ describe('On Completion', () => { }) it('provides suggestions for direcitive statement after keywords "include", "inherit" and "requrie" are typed', async () => { - jest.spyOn(bitBakeProjectScanner, 'includes', 'get').mockReturnValue([{ - name: 'init-manager-none', - path: { - root: '/', - dir: '/home/projects/poky/meta/conf/distro/include', - base: 'init-manager-none.inc', - ext: '.inc', - name: 'init-manager-none' + const documentUri = 'file:///home/projects/poky/meta/conf-2/path/to/dummy.bb' + jest.spyOn(bitBakeProjectScanner, 'includes', 'get').mockReturnValue([ + { + name: 'init-manager-none', + path: { + root: '/', + dir: '/home/projects/poky/meta/conf/distro/include', + base: 'init-manager-none.inc', + ext: '.inc', + name: 'init-manager-none' + }, + extraInfo: 'layer: core', + layerInfo: { + name: 'core', + path: '/home/projects/poky/meta', + priority: 5 + } }, - extraInfo: 'layer: core', - layerInfo: { - name: 'core', - path: '/home/projects/poky/meta', - priority: 5 + { + name: 'init-manager-none-2', + path: { + root: '/', + dir: '/home/projects/poky/meta/conf-2/distro/include', // Note that this fake path is under the same "conf-2" folder as the documentUri + base: 'init-manager-none-2.inc', + ext: '.inc', + name: 'init-manager-none-2' + }, + extraInfo: 'layer: core', + layerInfo: { + name: 'core', + path: '/home/projects/poky/meta', + priority: 5 + } } - }]) + ]) jest.spyOn(bitBakeProjectScanner, 'classes', 'get').mockReturnValue([{ name: 'copyleft_filter', @@ -439,13 +458,13 @@ describe('On Completion', () => { }]) await analyzer.analyze({ - uri: DUMMY_URI, + uri: documentUri, document: FIXTURE_DOCUMENT.COMPLETION }) const resultForInclude = onCompletionHandler({ textDocument: { - uri: DUMMY_URI + uri: documentUri }, position: { line: 10, @@ -455,7 +474,7 @@ describe('On Completion', () => { const resultForRequire = onCompletionHandler({ textDocument: { - uri: DUMMY_URI + uri: documentUri }, position: { line: 11, @@ -465,7 +484,7 @@ describe('On Completion', () => { const resultForInherit = onCompletionHandler({ textDocument: { - uri: DUMMY_URI + uri: documentUri }, position: { line: 12, @@ -477,7 +496,7 @@ describe('On Completion', () => { expect.arrayContaining([ expect.objectContaining( { - label: 'init-manager-none', + label: 'init-manager-none.inc', kind: 8, insertText: 'conf/distro/include/init-manager-none.inc' } @@ -485,11 +504,16 @@ describe('On Completion', () => { ]) ) + const index1 = resultForInclude.findIndex((item) => item.label === 'init-manager-none.inc') + const index2 = resultForInclude.findIndex((item) => item.label === 'init-manager-none-2.inc') + // Since the path of "init-manager-none-2.inc" is under the same "conf-2" folder as the documentUri, it should be suggested first + expect(index2).toBeLessThan(index1) + expect(resultForRequire).toEqual( expect.arrayContaining([ expect.objectContaining( { - label: 'init-manager-none', + label: 'init-manager-none.inc', kind: 8, insertText: 'conf/distro/include/init-manager-none.inc' } diff --git a/server/src/connectionHandlers/onCompletion.ts b/server/src/connectionHandlers/onCompletion.ts index 5764a4f5..88e45e37 100644 --- a/server/src/connectionHandlers/onCompletion.ts +++ b/server/src/connectionHandlers/onCompletion.ts @@ -21,6 +21,8 @@ import { VARIABLE_FLAGS } from '../completions/variable-flags' import { bitBakeProjectScanner } from '../BitBakeProjectScanner' import type { ElementInfo } from '../lib/src/types/BitbakeScanResult' +let documentUri = '' + export function onCompletionHandler (textDocumentPositionParams: TextDocumentPositionParams): CompletionItem[] { const wordPosition = { line: textDocumentPositionParams.position.line, @@ -28,7 +30,7 @@ export function onCompletionHandler (textDocumentPositionParams: TextDocumentPos character: Math.max(textDocumentPositionParams.position.character - 1, 0) } - const documentUri = textDocumentPositionParams.textDocument.uri + documentUri = textDocumentPositionParams.textDocument.uri const word = analyzer.wordAtPointFromTextPosition({ ...textDocumentPositionParams, @@ -222,7 +224,7 @@ function convertElementInfoListToCompletionItemList (elementInfoList: ElementInf for (const element of elementInfoList) { const filePath = getFilePath(element, fileType) const completionItem: CompletionItem = { - label: element.name, + label: element.name + (element.path?.ext === '.inc' ? '.inc' : ''), labelDetails: { description: filePath ?? fileType }, @@ -234,6 +236,19 @@ function convertElementInfoListToCompletionItemList (elementInfoList: ElementInf completionItems.push(completionItem) } + if (completionItems.length > 0) { + const docUriSplit = documentUri.replace('file://', '').split('/') + const condition = (item: CompletionItem): boolean => { + if (item.insertText === undefined || item.insertText.split('.')[0] === item.label.split('.')[0]) { + return false + } else { + return docUriSplit.includes(item.insertText.split('/')[0]) + } + } + + completionItems.sort((a, b) => Number(condition(b)) - Number(condition(a))) + } + return completionItems }