diff --git a/packages/apidom-ls/src/apidom-language-types.ts b/packages/apidom-ls/src/apidom-language-types.ts index 387568f7d..4e004c7ed 100644 --- a/packages/apidom-ls/src/apidom-language-types.ts +++ b/packages/apidom-ls/src/apidom-language-types.ts @@ -324,6 +324,8 @@ export enum CompletionFormat { ARRAY, ARRAY_OBJECT, UNDEFINED, + PARTIAL_KEY, + PARTIAL_KEY_QUOTED, } export interface ApidomCompletionItem extends CompletionItem { diff --git a/packages/apidom-ls/src/config/openapi/callback/completion.ts b/packages/apidom-ls/src/config/openapi/callback/completion.ts index bf8db4a11..54a78d2ae 100644 --- a/packages/apidom-ls/src/config/openapi/callback/completion.ts +++ b/packages/apidom-ls/src/config/openapi/callback/completion.ts @@ -17,6 +17,186 @@ const completion: ApidomCompletionItem[] = [ value: 'A reference to a Callback.', }, }, + { + label: '$url', + insertText: "'\\$url'", + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request URL', + }, + }, + { + label: '$method', + insertText: "'\\$method'", + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'HTTP Method', + }, + }, + { + label: '$statusCode', + insertText: "'\\$statusCode'", + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Status Code', + }, + }, + { + label: '$request.path...', + insertText: '\\$request.path.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request Path', + }, + }, + { + label: '$request.query...', + insertText: '\\$request.query.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request Query', + }, + }, + { + label: '$request.header...', + insertText: '\\$request.header.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request Header', + }, + }, + { + label: '$request.header...', + insertText: '\\$request.header.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request Header', + }, + }, + { + label: '$request.body', + insertText: "'\\$request.body'", + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request Body', + }, + }, + { + label: '$request.body#/...', + insertText: '\\$request.body#/.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Request Body..', + }, + }, + { + label: '$response.path...', + insertText: '\\$response.path.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Response Path', + }, + }, + { + label: '$response.query...', + insertText: '\\$response.query.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Response Query', + }, + }, + { + label: '$response.header...', + insertText: '\\$response.header.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Response Header', + }, + }, + { + label: '$response.header...', + insertText: '\\$response.header.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Response Header', + }, + }, + { + label: '$response.body', + insertText: "'\\$response.body'", + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Response Body', + }, + }, + { + label: '$response.body#/...', + insertText: '\\$response.body#/.', + kind: 14, + format: CompletionFormat.PARTIAL_KEY_QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'Response Body..', + }, + }, ]; export default completion; diff --git a/packages/apidom-ls/src/services/completion/completion-service.ts b/packages/apidom-ls/src/services/completion/completion-service.ts index d1d0cfd21..5462dc8f5 100644 --- a/packages/apidom-ls/src/services/completion/completion-service.ts +++ b/packages/apidom-ls/src/services/completion/completion-service.ts @@ -1318,6 +1318,20 @@ export class DefaultCompletionService implements CompletionService { targetItem.insertText = `"${targetItem.insertText}": "$1"`; } break; + case CompletionFormat.PARTIAL_KEY: + if (yaml) { + targetItem.insertText = `${targetItem.insertText}$1: `; + } else { + targetItem.insertText = `"${targetItem.insertText}$1": `; + } + break; + case CompletionFormat.PARTIAL_KEY_QUOTED: + if (yaml) { + targetItem.insertText = `'${targetItem.insertText}$1': `; + } else { + targetItem.insertText = `"${targetItem.insertText}$1": `; + } + break; default: // } diff --git a/packages/apidom-ls/test/complete.ts b/packages/apidom-ls/test/complete.ts index 402104893..1de7b0258 100644 --- a/packages/apidom-ls/test/complete.ts +++ b/packages/apidom-ls/test/complete.ts @@ -1333,4 +1333,123 @@ describe('apidom-ls-complete', function () { }, ] as ApidomCompletionItem[]); }); + + it('openapi / yaml - test callback completion issue 2356', async function () { + const completionContext: CompletionContext = { + maxNumberOfItems: 100, + }; + + const spec = fs + .readFileSync(path.join(__dirname, 'fixtures', 'completion', 'oas', 'issue-2356.yaml')) + .toString(); + + const doc: TextDocument = TextDocument.create('foo://bar/issue-2356.yaml', 'yaml', 0, spec); + + const pos = Position.create(7, 10); + const result = await languageService.doCompletion( + doc, + { textDocument: doc, position: pos }, + completionContext, + ); + assert.deepEqual(result!.items, [ + { + label: '$ref', + insertText: '\\$ref: $1', + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'A reference to a Callback.' }, + }, + { + label: '$url', + insertText: "'\\$url': \n $1", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Request URL' }, + }, + { + label: '$method', + insertText: "'\\$method': \n $1", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'HTTP Method' }, + }, + { + label: '$statusCode', + insertText: "'\\$statusCode': \n $1", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Status Code' }, + }, + { + label: '$request.path...', + insertText: "'\\$request.path.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Request Path' }, + }, + { + label: '$request.query...', + insertText: "'\\$request.query.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Request Query' }, + }, + { + label: '$request.header...', + insertText: "'\\$request.header.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Request Header' }, + }, + { + label: '$request.body', + insertText: "'\\$request.body': \n $1", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Request Body' }, + }, + { + label: '$request.body#/...', + insertText: "'\\$request.body#/.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Request Body..' }, + }, + { + label: '$response.path...', + insertText: "'\\$response.path.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Response Path' }, + }, + { + label: '$response.query...', + insertText: "'\\$response.query.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Response Query' }, + }, + { + label: '$response.header...', + insertText: "'\\$response.header.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Response Header' }, + }, + { + label: '$response.body', + insertText: "'\\$response.body': \n $1", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Response Body' }, + }, + { + label: '$response.body#/...', + insertText: "'\\$response.body#/.$1': ", + kind: 14, + insertTextFormat: 2, + documentation: { kind: 'markdown', value: 'Response Body..' }, + }, + ] as ApidomCompletionItem[]); + }); }); diff --git a/packages/apidom-ls/test/fixtures/completion/oas/issue-2356.yaml b/packages/apidom-ls/test/fixtures/completion/oas/issue-2356.yaml new file mode 100644 index 000000000..c610bbc7c --- /dev/null +++ b/packages/apidom-ls/test/fixtures/completion/oas/issue-2356.yaml @@ -0,0 +1,8 @@ +openapi: 3.1.0 +paths: + /pet: + put: + operationId: updatePet + callbacks: + test: +