From bda628a51a0896946d4601756b80909ef2a8e17a Mon Sep 17 00:00:00 2001 From: Petr Spacek Date: Tue, 12 Jan 2021 12:43:32 +0100 Subject: [PATCH 1/3] fix: completion array anyOf #5 --- .../services/yamlCompletion.ts | 28 ++++- test/autoCompletion.test.ts | 104 ++++++++++++++++++ test/fixtures/testArrayCompletionSchema.json | 85 ++++++++++++++ 3 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/testArrayCompletionSchema.json diff --git a/src/languageservice/services/yamlCompletion.ts b/src/languageservice/services/yamlCompletion.ts index 5f384e50..462c9cac 100644 --- a/src/languageservice/services/yamlCompletion.ts +++ b/src/languageservice/services/yamlCompletion.ts @@ -30,7 +30,7 @@ import { stringifyObject, StringifySettings } from '../utils/json'; import { guessIndentation } from '../utils/indentationGuesser'; import { TextBuffer } from '../utils/textBuffer'; import { setKubernetesParserOption } from '../parser/isKubernetes'; -import { ClientCapabilities } from 'vscode-languageserver'; +import { ClientCapabilities, MarkupContent } from 'vscode-languageserver'; const localize = nls.loadMessageBundle(); export class YAMLCompletion extends JSONCompletion { @@ -388,6 +388,25 @@ export class YAMLCompletion extends JSONCompletion { insertTextFormat: InsertTextFormat.Snippet, }); this.addSchemaValueCompletions(s.schema.items, separatorAfter, collector, types); + } else if (typeof s.schema.items === 'object' && s.schema.items.anyOf) { + s.schema.items.anyOf + .filter((i) => typeof i === 'object') + .forEach((i: JSONSchema, index) => { + const insertText = `- ${this.getInsertTextForObject(i, separatorAfter).insertText.trimLeft()}`; + //append insertText to documentation + const documentation = this.getDocumentationWithMarkdownText( + `Create an item of an array${s.schema.description === undefined ? '' : '(' + s.schema.description + ')'}`, + insertText + ); + collector.add({ + kind: super.getSuggestionKind(i.type), + label: '- (array item) ' + (index + 1), + documentation: documentation, + insertText: insertText, + insertTextFormat: InsertTextFormat.Snippet, + }); + }); + this.addSchemaValueCompletions(s.schema.items, separatorAfter, collector, types); } else { this.addSchemaValueCompletions(s.schema.items, separatorAfter, collector, types); } @@ -999,6 +1018,13 @@ export class YAMLCompletion extends JSONCompletion { private is_EOL(c: number): boolean { return c === 0x0a /* LF */ || c === 0x0d /* CR */; } + + private getDocumentationWithMarkdownText(documentation: string, insertText: string): string | MarkupContent { + const res = super.doesSupportMarkdown() + ? (super.fromMarkup(`${documentation}\n \`\`\`\n${insertText}\n\`\`\``) as MarkupContent) + : documentation; + return res; + } } const isNumberExp = /^\d+$/; diff --git a/test/autoCompletion.test.ts b/test/autoCompletion.test.ts index acfcb3a8..39516768 100644 --- a/test/autoCompletion.test.ts +++ b/test/autoCompletion.test.ts @@ -1710,5 +1710,109 @@ suite('Auto Completion Tests', () => { ); }); }); + describe('Array completion', () => { + //test_simpleArrayObject + // it('Simple array object completion without "-" without any item', async () => { + // const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + // languageService.addSchema(SCHEMA_ID, schema); + // const content = 'test_simpleArrayObject:\n '; + // const completion = parseSetup(content, content.length); + // completion.then(function (result) { + // assert.equal(result.items.length, 1); + // assert.equal(result.items[0]?.label, '- (array item)'); + // }); + // }); + //worked ok + it('Simple array object completion with "-" without any item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_simpleArrayObject:\n -'; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 1); + assert.equal(result.items[0].label, '- (array item)'); + }); + }); + //worked ok + it('Simple array object completion without "-" after array item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_simpleArrayObject:\n - obj1:\n name: 1\n '; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 1); + assert.equal(result.items[0].label, '- (array item)'); + }); + }); + //worked ok + it('Simple array object completion with "-" after array item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_simpleArrayObject:\n - obj1:\n name: 1\n -'; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 1); + assert.equal(result.items[0].label, '- (array item)'); + }); + }); + + //test_array_anyOf_2objects + // it('Array anyOf two objects completion without "-" without any item', async () => { + // const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + // languageService.addSchema(SCHEMA_ID, schema); + // const content = 'test_array_anyOf_2objects:\n '; + // const completion = parseSetup(content, content.length); + // completion.then(function (result) { + // assert.equal(result.items.length, 1); + // assert.equal(result.items[0].label, '- (array item)'); + // }); + // }); + + //worked ok + it('Array anyOf two objects completion with "- " without any item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_array_anyOf_2objects:\n - '; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 2); + assert.equal(result.items[0].label, 'obj1'); + }); + }); + + it('Array anyOf two objects completion with "-" without any item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_array_anyOf_2objects:\n -'; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 2); + assert.equal(result.items[0].label, '- (array item) 1'); + }); + }); + + it('Array anyOf two objects completion without "-" after array item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_array_anyOf_2objects:\n - obj1:\n name: 1\n '; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 2); + assert.equal(result.items[0].label, '- (array item) 1'); + }); + }); + + //worked ok + it('Array anyOf two objects completion with "-" after array item', async () => { + const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); + languageService.addSchema(SCHEMA_ID, schema); + const content = 'test_array_anyOf_2objects:\n - obj1:\n name: 1\n -'; + const completion = parseSetup(content, content.length); + completion.then(function (result) { + assert.equal(result.items.length, 2); + assert.equal(result.items[0].label, '- (array item) 1'); + }); + }); + }); }); }); diff --git a/test/fixtures/testArrayCompletionSchema.json b/test/fixtures/testArrayCompletionSchema.json new file mode 100644 index 00000000..6459e10a --- /dev/null +++ b/test/fixtures/testArrayCompletionSchema.json @@ -0,0 +1,85 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "obj1": { + "properties": { + "obj1": { + "type": "object" + } + }, + "required": [ + "obj1" + ], + "type": "object" + }, + "obj2": { + "properties": { + "obj2": { + "type": "object" + } + }, + "required": [ + "obj2" + ], + "type": "object" + } + }, + "properties": { + "test_simpleArrayObject": { + "items": { + "$ref": "#/definitions/obj1" + }, + "type": "array" + }, + "test_array_anyOf_2objects": { + "items": { + "anyOf": [ + { + "$ref": "#/definitions/obj1" + }, + { + "$ref": "#/definitions/obj2" + } + ] + }, + "type": "array" + }, + "test_array_anyOf_strAndObj": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/obj1" + } + ] + }, + "type": "array" + }, + "test_anyOfObjectAndNull": { + "anyOf": [ + { + "$ref": "#/definitions/obj1" + }, + { + "type": "null" + } + ] + }, + "test_anyOfArrAndNull": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + } \ No newline at end of file From b607c2f876012e3be62f641f970156c35894ad1f Mon Sep 17 00:00:00 2001 From: Petr Spacek Date: Tue, 12 Jan 2021 13:44:20 +0100 Subject: [PATCH 2/3] fix: completion array anyOf - remove $1 from preview --- src/languageservice/services/yamlCompletion.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/languageservice/services/yamlCompletion.ts b/src/languageservice/services/yamlCompletion.ts index 462c9cac..ddfdc156 100644 --- a/src/languageservice/services/yamlCompletion.ts +++ b/src/languageservice/services/yamlCompletion.ts @@ -1020,9 +1020,15 @@ export class YAMLCompletion extends JSONCompletion { } private getDocumentationWithMarkdownText(documentation: string, insertText: string): string | MarkupContent { - const res = super.doesSupportMarkdown() - ? (super.fromMarkup(`${documentation}\n \`\`\`\n${insertText}\n\`\`\``) as MarkupContent) - : documentation; + let res: string | MarkupContent = documentation; + if (super.doesSupportMarkdown()) { + insertText = insertText + .replace(/\${[0-9]+[:|](.*)}/g, (s, arg) => { + return arg; + }) + .replace(/\$([0-9]+)/g, ''); + res = super.fromMarkup(`${documentation}\n \`\`\`\n${insertText}\n\`\`\``) as MarkupContent; + } return res; } } From 252c1e83c99394d2536b58c08057e2d37d3b7187 Mon Sep 17 00:00:00 2001 From: Petr Spacek Date: Thu, 14 Jan 2021 11:22:57 +0100 Subject: [PATCH 3/3] fix: remove comments from test --- test/autoCompletion.test.ts | 30 ++------------------ test/fixtures/testArrayCompletionSchema.json | 2 +- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/test/autoCompletion.test.ts b/test/autoCompletion.test.ts index 39516768..a974dd68 100644 --- a/test/autoCompletion.test.ts +++ b/test/autoCompletion.test.ts @@ -1711,18 +1711,6 @@ suite('Auto Completion Tests', () => { }); }); describe('Array completion', () => { - //test_simpleArrayObject - // it('Simple array object completion without "-" without any item', async () => { - // const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); - // languageService.addSchema(SCHEMA_ID, schema); - // const content = 'test_simpleArrayObject:\n '; - // const completion = parseSetup(content, content.length); - // completion.then(function (result) { - // assert.equal(result.items.length, 1); - // assert.equal(result.items[0]?.label, '- (array item)'); - // }); - // }); - //worked ok it('Simple array object completion with "-" without any item', async () => { const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); languageService.addSchema(SCHEMA_ID, schema); @@ -1733,7 +1721,7 @@ suite('Auto Completion Tests', () => { assert.equal(result.items[0].label, '- (array item)'); }); }); - //worked ok + it('Simple array object completion without "-" after array item', async () => { const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); languageService.addSchema(SCHEMA_ID, schema); @@ -1744,7 +1732,7 @@ suite('Auto Completion Tests', () => { assert.equal(result.items[0].label, '- (array item)'); }); }); - //worked ok + it('Simple array object completion with "-" after array item', async () => { const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); languageService.addSchema(SCHEMA_ID, schema); @@ -1756,19 +1744,6 @@ suite('Auto Completion Tests', () => { }); }); - //test_array_anyOf_2objects - // it('Array anyOf two objects completion without "-" without any item', async () => { - // const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); - // languageService.addSchema(SCHEMA_ID, schema); - // const content = 'test_array_anyOf_2objects:\n '; - // const completion = parseSetup(content, content.length); - // completion.then(function (result) { - // assert.equal(result.items.length, 1); - // assert.equal(result.items[0].label, '- (array item)'); - // }); - // }); - - //worked ok it('Array anyOf two objects completion with "- " without any item', async () => { const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); languageService.addSchema(SCHEMA_ID, schema); @@ -1802,7 +1777,6 @@ suite('Auto Completion Tests', () => { }); }); - //worked ok it('Array anyOf two objects completion with "-" after array item', async () => { const schema = require(path.join(__dirname, './fixtures/testArrayCompletionSchema.json')); languageService.addSchema(SCHEMA_ID, schema); diff --git a/test/fixtures/testArrayCompletionSchema.json b/test/fixtures/testArrayCompletionSchema.json index 6459e10a..0accf9ee 100644 --- a/test/fixtures/testArrayCompletionSchema.json +++ b/test/fixtures/testArrayCompletionSchema.json @@ -82,4 +82,4 @@ } }, "type": "object" - } \ No newline at end of file + }