From 92c852d34a6db15e27ce0483de9c50e6bffb0d98 Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Wed, 10 Jul 2024 14:43:53 -0700 Subject: [PATCH 1/7] Fix type completion issue by making sure the Json parser ignores incomplete string values --- src/parser/jsonParser.ts | 5 +- src/test/completion.test.ts | 145 ++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index 3336956..deeb01d 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -1347,7 +1347,10 @@ export function parse(textDocument: TextDocument, config?: JSONDocumentConfig): const node = new StringASTNodeImpl(parent, scanner.getTokenOffset()); node.value = scanner.getTokenValue(); - + if (scanner.getTokenError() === Json.ScanError.UnexpectedEndOfString && + parent?.type === 'property' && (parent?.keyNode?.value === '@type' || parent?.keyNode?.value === 'type')) { + return undefined; + } return _finalize(node, true); } diff --git a/src/test/completion.test.ts b/src/test/completion.test.ts index dc9a825..74cc9af 100644 --- a/src/test/completion.test.ts +++ b/src/test/completion.test.ts @@ -730,6 +730,151 @@ suite('JSON Completion', () => { }); }); + test('Complete with anyOf over $refs', async function () { + + const schema: JSONSchema = { + type: 'object', + properties: { + 'inner': { + type : 'array', + items : { + anyOf : [ { + $ref : '#/$defs/TypeDef1' + }, { + $ref : '#/$defs/TypeDef2' + }, { + $ref : '#/$defs/TypeDef3' + }, { + $ref : '#/$defs/TypeDef4' + } + ] + }, + } + }, + required : [ "inner" ], + additionalProperties : false, + $defs : { + TypeDef1 : { + type : "object", + properties : { + a : { + type: 'string', + description: 'A' + }, + "@type" : { + const : "TypeDef1" + } + }, + required : [ "@type" ], + additionalProperties : false, + description : "TypeDef1 Desc." + }, + TypeDef2 : { + type : "object", + properties : { + b : { + type: 'string', + description: 'B' + }, + "@type" : { + const : "TypeDef2" + } + }, + required : [ "@type" ], + additionalProperties : false, + description : "TypeDef2 Desc." + }, + TypeDef3 : { + type : "object", + properties : { + c : { + type: 'string', + description: 'C' + }, + "@type" : { + const : "TypeDef3" + } + }, + required : [ "@type", "c" ], + additionalProperties : false + }, + TypeDef4 : { + type : "object", + properties : { + d : { + type: 'boolean', + description: 'D' + }, + "@type" : { + const : "TypeDef4" + } + }, + required : [ "@type", "d" ], + additionalProperties : false + } + } + }; + await testCompletionsFor('{|}', schema, { + count: 1, + items: [ + { label: 'inner', resultText: '{"inner": [$1]}' } + ] + }); + await testCompletionsFor('{ "inner": [{|}]}', schema, { + count: 5, + items: [ + { label: '@type' }, + { label: 'a', documentation: 'A' }, + { label: 'b', documentation: 'B' }, + { label: 'c', documentation: 'C' }, + { label: 'd', documentation: 'D' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":|}]}', schema, { + count: 4, + items: [ + { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"}]}' }, + { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"}]}' }, + { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"}]}' }, + { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"}]}' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":"Type|', schema, { + count: 4, + items: [ + { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' }, + { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"' }, + { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"' }, + { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1|', schema, { + count: 4, + items: [ + { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' }, + { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"' }, + { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"' }, + { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":"|}]}', schema, { + count: 4, + items: [ + { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"}]}' }, + { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"}]}' }, + { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"}]}' }, + { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"}]}' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1", |}]}', schema, { + count: 1, + items: [ + { label: 'a', documentation: 'A' } + ] + }); + }); + + test('Complete with oneOf', async function () { const schema: JSONSchema = { From d872c5bb592f75a8394307b61b9f98f60d33dda7 Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Thu, 11 Jul 2024 11:33:30 -0700 Subject: [PATCH 2/7] Moving skip logic from parser to getValueCompletions for a less invasive approach --- src/parser/jsonParser.ts | 5 +---- src/services/jsonCompletion.ts | 5 +++++ src/test/completion.test.ts | 20 +++++++++++++++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index deeb01d..c4cec86 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -1347,10 +1347,7 @@ export function parse(textDocument: TextDocument, config?: JSONDocumentConfig): const node = new StringASTNodeImpl(parent, scanner.getTokenOffset()); node.value = scanner.getTokenValue(); - if (scanner.getTokenError() === Json.ScanError.UnexpectedEndOfString && - parent?.type === 'property' && (parent?.keyNode?.value === '@type' || parent?.keyNode?.value === 'type')) { - return undefined; - } + return _finalize(node, true); } diff --git a/src/services/jsonCompletion.ts b/src/services/jsonCompletion.ts index 90d4c9f..31c049b 100644 --- a/src/services/jsonCompletion.ts +++ b/src/services/jsonCompletion.ts @@ -442,6 +442,11 @@ export class JSONCompletion { if (node && (parentKey !== undefined || node.type === 'array')) { const separatorAfter = this.evaluateSeparatorAfter(document, offsetForSeparator); + // Making sure validation for matching schemas is bypassed when user is typing the type value + if ((parentKey === "type" || parentKey === "@type") && node.parent?.children?.length === 1) { + valueNode = undefined; + } + const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset, valueNode); for (const s of matchingSchemas) { if (s.node === node && !s.inverted && s.schema) { diff --git a/src/test/completion.test.ts b/src/test/completion.test.ts index 74cc9af..0dfd6eb 100644 --- a/src/test/completion.test.ts +++ b/src/test/completion.test.ts @@ -849,6 +849,12 @@ suite('JSON Completion', () => { ] }); await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1|', schema, { + count: 1, + items: [ + { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":"|}]}', schema, { count: 4, items: [ { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' }, @@ -857,7 +863,7 @@ suite('JSON Completion', () => { { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"|}]}', schema, { + await testCompletionsFor('{ "inner": [{ "@type":"|"}]}', schema, { count: 4, items: [ { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"}]}' }, @@ -866,6 +872,18 @@ suite('JSON Completion', () => { { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"}]}' } ] }); + await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1|" }]}', schema, { + count: 1, + items: [ + { label: '"TypeDef1"' } + ] + }); + await testCompletionsFor('{ "inner": [{ "@type":"TypeDef3|" }]}', schema, { + count: 1, + items: [ + { label: '"TypeDef3"' } + ] + }); await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1", |}]}', schema, { count: 1, items: [ From 581b2aed4bfc7151f26913d3804420073da8c18b Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Thu, 11 Jul 2024 11:39:55 -0700 Subject: [PATCH 3/7] Adding more unit tests --- src/parser/jsonParser.ts | 2 ++ src/test/completion.test.ts | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index c4cec86..1833725 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -380,6 +380,8 @@ function getSchemaDraft(schema: JSONSchema, fallBack = SchemaDraft.v2020_12) { function validate(n: ASTNode | undefined, schema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, context: IEvaluationContext): void { + // TODO: can we use a node property to skip validation for certain nodes + if (!n || !matchingSchemas.include(n)) { return; } diff --git a/src/test/completion.test.ts b/src/test/completion.test.ts index 0dfd6eb..7479d92 100644 --- a/src/test/completion.test.ts +++ b/src/test/completion.test.ts @@ -872,6 +872,12 @@ suite('JSON Completion', () => { { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"}]}' } ] }); + await testCompletionsFor('{ "inner": [{ "@type":"|", d:"1"}]}', schema, { + count: 1, + items: [ + { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4", d:"1"}]}' } + ] + }); await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1|" }]}', schema, { count: 1, items: [ From c889ce40afa0f8e8d88793c44dd857a6245bf868 Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Thu, 11 Jul 2024 12:09:02 -0700 Subject: [PATCH 4/7] formatting --- src/parser/jsonParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index 1833725..51cc931 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -1349,7 +1349,7 @@ export function parse(textDocument: TextDocument, config?: JSONDocumentConfig): const node = new StringASTNodeImpl(parent, scanner.getTokenOffset()); node.value = scanner.getTokenValue(); - + return _finalize(node, true); } From 6a48174ca6623c8f34392104dbbc5b190f3a3844 Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Thu, 11 Jul 2024 12:10:44 -0700 Subject: [PATCH 5/7] formatting --- src/parser/jsonParser.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index 51cc931..3336956 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -380,8 +380,6 @@ function getSchemaDraft(schema: JSONSchema, fallBack = SchemaDraft.v2020_12) { function validate(n: ASTNode | undefined, schema: JSONSchema, validationResult: ValidationResult, matchingSchemas: ISchemaCollector, context: IEvaluationContext): void { - // TODO: can we use a node property to skip validation for certain nodes - if (!n || !matchingSchemas.include(n)) { return; } From fef260c72347aefa67476807f6b56e257ff9d041 Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Wed, 17 Jul 2024 16:29:10 -0700 Subject: [PATCH 6/7] After closer examination, I found where schemas are validated based on the node and moved the logic to do not execute the required fields validation if the current object only has the type defined. --- src/parser/jsonParser.ts | 3 +- src/services/jsonCompletion.ts | 5 -- src/test/completion.test.ts | 137 ++++++++------------------------- 3 files changed, 36 insertions(+), 109 deletions(-) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index 3336956..d441081 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -887,7 +887,8 @@ function validate(n: ASTNode | undefined, schema: JSONSchema, validationResult: unprocessedProperties.add(key); } - if (Array.isArray(schema.required)) { + // Only check required properties if node already has more than one property defined or if the existing property is the "type" + if (!(node.children?.length === 1 && (seenKeys["@type"] || seenKeys["type"])) && Array.isArray(schema.required)) { for (const propertyName of schema.required) { if (!seenKeys[propertyName]) { const keyNode = node.parent && node.parent.type === 'property' && node.parent.keyNode; diff --git a/src/services/jsonCompletion.ts b/src/services/jsonCompletion.ts index 31c049b..90d4c9f 100644 --- a/src/services/jsonCompletion.ts +++ b/src/services/jsonCompletion.ts @@ -442,11 +442,6 @@ export class JSONCompletion { if (node && (parentKey !== undefined || node.type === 'array')) { const separatorAfter = this.evaluateSeparatorAfter(document, offsetForSeparator); - // Making sure validation for matching schemas is bypassed when user is typing the type value - if ((parentKey === "type" || parentKey === "@type") && node.parent?.children?.length === 1) { - valueNode = undefined; - } - const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset, valueNode); for (const s of matchingSchemas) { if (s.node === node && !s.inverted && s.schema) { diff --git a/src/test/completion.test.ts b/src/test/completion.test.ts index 7479d92..1fd2359 100644 --- a/src/test/completion.test.ts +++ b/src/test/completion.test.ts @@ -733,26 +733,12 @@ suite('JSON Completion', () => { test('Complete with anyOf over $refs', async function () { const schema: JSONSchema = { - type: 'object', - properties: { - 'inner': { - type : 'array', - items : { - anyOf : [ { - $ref : '#/$defs/TypeDef1' - }, { - $ref : '#/$defs/TypeDef2' - }, { - $ref : '#/$defs/TypeDef3' - }, { - $ref : '#/$defs/TypeDef4' - } - ] - }, + anyOf : [ { + $ref : '#/$defs/TypeDef1' + }, { + $ref : '#/$defs/TypeDef2' } - }, - required : [ "inner" ], - additionalProperties : false, + ], $defs : { TypeDef1 : { type : "object", @@ -767,7 +753,6 @@ suite('JSON Completion', () => { }, required : [ "@type" ], additionalProperties : false, - description : "TypeDef1 Desc." }, TypeDef2 : { type : "object", @@ -780,117 +765,62 @@ suite('JSON Completion', () => { const : "TypeDef2" } }, - required : [ "@type" ], + required : [ "@type", "b" ], additionalProperties : false, description : "TypeDef2 Desc." - }, - TypeDef3 : { - type : "object", - properties : { - c : { - type: 'string', - description: 'C' - }, - "@type" : { - const : "TypeDef3" - } - }, - required : [ "@type", "c" ], - additionalProperties : false - }, - TypeDef4 : { - type : "object", - properties : { - d : { - type: 'boolean', - description: 'D' - }, - "@type" : { - const : "TypeDef4" - } - }, - required : [ "@type", "d" ], - additionalProperties : false } } }; await testCompletionsFor('{|}', schema, { - count: 1, - items: [ - { label: 'inner', resultText: '{"inner": [$1]}' } - ] - }); - await testCompletionsFor('{ "inner": [{|}]}', schema, { - count: 5, + count: 3, items: [ { label: '@type' }, { label: 'a', documentation: 'A' }, - { label: 'b', documentation: 'B' }, - { label: 'c', documentation: 'C' }, - { label: 'd', documentation: 'D' } - ] - }); - await testCompletionsFor('{ "inner": [{ "@type":|}]}', schema, { - count: 4, - items: [ - { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"}]}' }, - { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"}]}' }, - { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"}]}' }, - { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"}]}' } - ] - }); - await testCompletionsFor('{ "inner": [{ "@type":"Type|', schema, { - count: 4, - items: [ - { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' }, - { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"' }, - { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"' }, - { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"' } + { label: 'b', documentation: 'B' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1|', schema, { - count: 1, + await testCompletionsFor('{ "@type":|}', schema, { + count: 2, items: [ - { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' } + { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"}' }, + { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2"}' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"|}]}', schema, { - count: 4, + await testCompletionsFor('{ "@type":"Type|', schema, { + count: 2, items: [ - { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"' }, - { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"' }, - { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"' }, - { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"' } + { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"' }, + { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2"' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"|"}]}', schema, { - count: 4, + await testCompletionsFor('{ "@type":"TypeDef1|', schema, { + count: 2, items: [ - { label: '"TypeDef1"', resultText: '{ "inner": [{ "@type":"TypeDef1"}]}' }, - { label: '"TypeDef2"', resultText: '{ "inner": [{ "@type":"TypeDef2"}]}' }, - { label: '"TypeDef3"', resultText: '{ "inner": [{ "@type":"TypeDef3"}]}' }, - { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4"}]}' } + { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"' }, + { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2"' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"|", d:"1"}]}', schema, { - count: 1, + await testCompletionsFor('{ "@type":"|}', schema, { + count: 2, items: [ - { label: '"TypeDef4"', resultText: '{ "inner": [{ "@type":"TypeDef4", d:"1"}]}' } + { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"' }, + { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2"' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1|" }]}', schema, { - count: 1, + await testCompletionsFor('{ "@type":"|"}', schema, { + count: 2, items: [ - { label: '"TypeDef1"' } + { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"}' }, + { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2"}' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"TypeDef3|" }]}', schema, { + await testCompletionsFor('{ "@type":"|", b:"1"}', schema, { count: 1, items: [ - { label: '"TypeDef3"' } + { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2", b:"1"}' } ] }); - await testCompletionsFor('{ "inner": [{ "@type":"TypeDef1", |}]}', schema, { + await testCompletionsFor('{ "@type":"TypeDef1", |}', schema, { count: 1, items: [ { label: 'a', documentation: 'A' } @@ -898,7 +828,6 @@ suite('JSON Completion', () => { }); }); - test('Complete with oneOf', async function () { const schema: JSONSchema = { @@ -1578,20 +1507,22 @@ suite('JSON Completion', () => { } }] }; - await testCompletionsFor('{ "type": |', schema, { + count: 2, items: [ { label: '"foo"' }, { label: '"bar"' } ] }); await testCompletionsFor('{ "type": "f|', schema, { + count: 2, items: [ { label: '"foo"' }, { label: '"bar"' } ] }); await testCompletionsFor('{ "type": "foo|"', schema, { + count: 2, items: [ { label: '"foo"' }, { label: '"bar"' } From 33e42cdbe5259677a001671155151f60e4e88d0a Mon Sep 17 00:00:00 2001 From: Mario Martins Date: Thu, 18 Jul 2024 09:54:19 -0700 Subject: [PATCH 7/7] Reverting last changes since it could affect validation output along with auto-complete suggestions --- src/parser/jsonParser.ts | 3 +-- src/services/jsonCompletion.ts | 4 ++++ src/test/completion.test.ts | 10 ++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/parser/jsonParser.ts b/src/parser/jsonParser.ts index d441081..3336956 100644 --- a/src/parser/jsonParser.ts +++ b/src/parser/jsonParser.ts @@ -887,8 +887,7 @@ function validate(n: ASTNode | undefined, schema: JSONSchema, validationResult: unprocessedProperties.add(key); } - // Only check required properties if node already has more than one property defined or if the existing property is the "type" - if (!(node.children?.length === 1 && (seenKeys["@type"] || seenKeys["type"])) && Array.isArray(schema.required)) { + if (Array.isArray(schema.required)) { for (const propertyName of schema.required) { if (!seenKeys[propertyName]) { const keyNode = node.parent && node.parent.type === 'property' && node.parent.keyNode; diff --git a/src/services/jsonCompletion.ts b/src/services/jsonCompletion.ts index 90d4c9f..f813370 100644 --- a/src/services/jsonCompletion.ts +++ b/src/services/jsonCompletion.ts @@ -442,6 +442,10 @@ export class JSONCompletion { if (node && (parentKey !== undefined || node.type === 'array')) { const separatorAfter = this.evaluateSeparatorAfter(document, offsetForSeparator); + if ((parentKey === "type" || parentKey === "@type") && node.children?.length === 1) { + valueNode = undefined; + } + const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset, valueNode); for (const s of matchingSchemas) { if (s.node === node && !s.inverted && s.schema) { diff --git a/src/test/completion.test.ts b/src/test/completion.test.ts index 1fd2359..3dee1ea 100644 --- a/src/test/completion.test.ts +++ b/src/test/completion.test.ts @@ -794,10 +794,9 @@ suite('JSON Completion', () => { ] }); await testCompletionsFor('{ "@type":"TypeDef1|', schema, { - count: 2, + count: 1, items: [ - { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"' }, - { label: '"TypeDef2"', resultText: '{ "@type":"TypeDef2"' } + { label: '"TypeDef1"', resultText: '{ "@type":"TypeDef1"' } ] }); await testCompletionsFor('{ "@type":"|}', schema, { @@ -1522,10 +1521,9 @@ suite('JSON Completion', () => { ] }); await testCompletionsFor('{ "type": "foo|"', schema, { - count: 2, + count: 1, items: [ - { label: '"foo"' }, - { label: '"bar"' } + { label: '"foo"' } ] }); });