diff --git a/src/languageservice/parser/yaml-documents.ts b/src/languageservice/parser/yaml-documents.ts index 3fb99ddd..e4abc7bb 100644 --- a/src/languageservice/parser/yaml-documents.ts +++ b/src/languageservice/parser/yaml-documents.ts @@ -197,7 +197,12 @@ export class SingleYAMLDocument extends JSONDocument { const position = textBuffer.getPosition(node.range[0]); const lineContent = textBuffer.getLineContent(position.line); currentLine = currentLine === '' ? lineContent.trim() : currentLine; - if (currentLine.startsWith('-') && indentation === configuredIndentation && currentLine === lineContent.trim()) { + if ( + currentLine.startsWith('-') && + indentation === configuredIndentation && + indentation === getIndentation(lineContent, position.character) && + currentLine === lineContent.trim() + ) { position.character += indentation; } if (position.character > indentation && position.character > 0) { diff --git a/src/languageservice/services/yamlCompletion.ts b/src/languageservice/services/yamlCompletion.ts index 513a23d6..de159b07 100644 --- a/src/languageservice/services/yamlCompletion.ts +++ b/src/languageservice/services/yamlCompletion.ts @@ -477,20 +477,6 @@ export class YamlCompletion { node = pair.value; } } - } else if (isSeq(node)) { - if (lineContent.charAt(position.character - 1) !== '-') { - const map = this.createTempObjNode(currentWord, node, currentDoc); - map.items = []; - currentDoc.updateFromInternalDocument(); - for (const pair of node.items) { - if (isMap(pair)) { - pair.items.forEach((value) => { - map.items.push(value); - }); - } - } - node = map; - } } } } @@ -692,9 +678,7 @@ export class YamlCompletion { } for (const schema of matchingSchemas) { if ( - ((schema.node.internalNode === node && !matchOriginal) || - (schema.node.internalNode === originalNode && !hasColon) || - (schema.node.parent?.internalNode === originalNode && !hasColon)) && + ((schema.node.internalNode === node && !matchOriginal) || (schema.node.internalNode === originalNode && !hasColon)) && !schema.inverted ) { this.collectDefaultSnippets(schema.schema, separatorAfter, collector, { diff --git a/test/autoCompletion.test.ts b/test/autoCompletion.test.ts index eba8fa6d..6be38564 100644 --- a/test/autoCompletion.test.ts +++ b/test/autoCompletion.test.ts @@ -2251,6 +2251,69 @@ describe('Auto Completion Tests', () => { expect(completion.items[0].insertText).eq('prop2: '); }); + it('should complete properties of an object under an array', async () => { + schemaProvider.addSchema(SCHEMA_ID, { + type: 'object', + properties: { + steps: { + type: 'array', + items: { + type: 'object', + properties: { + task: { + type: 'string', + }, + inputs: { + type: 'string', + }, + }, + }, + }, + name: { + type: 'string', + }, + }, + }); + + // Thanks to the indentation, the intent is clear: continue adding to the current object. + const content = 'steps:\n- task: PowerShell@2\n '; // len: 30 + const completion = await parseSetup(content, 30); + expect(completion.items).lengthOf(1); + expect(completion.items[0].label).eq('inputs'); + }); + + it('should not show bare property completions for array items when the cursor indentation is ambiguous', async () => { + schemaProvider.addSchema(SCHEMA_ID, { + type: 'object', + properties: { + steps: { + type: 'array', + items: { + type: 'object', + properties: { + task: { + type: 'string', + }, + inputs: { + type: 'string', + }, + }, + }, + }, + name: { + type: 'string', + }, + }, + }); + + // Here, the intent _could_ be to move out of the array, or it could be to continue adding to the array. + // Thus, `name: ` is fine and so is `- task: `, but _not_ a bare `task: `. + const content = 'steps:\n- task: PowerShell@2\n'; // len: 28 + const completion = await parseSetup(content, 28); + expect(completion.items[0].label).eq('name'); + expect(completion.items.slice(1).filter((item) => !item.insertText.startsWith('- '))).to.be.empty; + }); + it('should complete string which contains number in default value', async () => { schemaProvider.addSchema(SCHEMA_ID, { type: 'object', diff --git a/test/autoCompletionFix.test.ts b/test/autoCompletionFix.test.ts index c720ce76..28cced44 100644 --- a/test/autoCompletionFix.test.ts +++ b/test/autoCompletionFix.test.ts @@ -129,16 +129,16 @@ describe('Auto Completion Fix Tests', () => { }, }, }); - const content = '- prop1: a\n | |'; // len: 12, pos: 11 - const completion = await parseCaret(content); + const content = '- prop1: a\n '; // len: 13 + const completion = await parseSetup(content, 1, 2); expect(completion.items).lengthOf(2); expect(completion.items[0]).eql( - createExpectedCompletion('prop2', 'prop2: ', 1, 3, 1, 4, 10, 2, { + createExpectedCompletion('prop2', 'prop2: ', 1, 2, 1, 2, 10, 2, { documentation: '', }) ); expect(completion.items[1]).eql( - createExpectedCompletion('prop3', 'prop3: ', 1, 3, 1, 4, 10, 2, { + createExpectedCompletion('prop3', 'prop3: ', 1, 2, 1, 2, 10, 2, { documentation: '', }) );