From b7e6e6fae7fb2f0e5e5dda5730f67d23acc6e5ce Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 10 Feb 2016 12:09:34 +0100 Subject: [PATCH] [json] better support for null, and array of types --- extensions/json/server/src/jsonCompletion.ts | 33 ++++++++++++++----- extensions/json/server/src/jsonParser.ts | 2 +- .../json/server/src/test/completion.test.ts | 30 ++++++++++++++++- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/extensions/json/server/src/jsonCompletion.ts b/extensions/json/server/src/jsonCompletion.ts index aea7308cd84..779b66055a7 100644 --- a/extensions/json/server/src/jsonCompletion.ts +++ b/extensions/json/server/src/jsonCompletion.ts @@ -73,7 +73,7 @@ export class JSONCompletion { let addValue = true; let currentKey = ''; - + let currentProperty: Parser.PropertyASTNode = null; if (node) { @@ -134,8 +134,8 @@ export class JSONCompletion { } else { // value proposals without schema this.getSchemaLessValueSuggestions(doc, node, offset, document, collector); - } - + } + if (!node) { this.contributions.forEach((contribution) => { let collectPromise = contribution.collectDefaultSuggestions(textDocumentPosition.uri, collector); @@ -305,12 +305,21 @@ export class JSONCompletion { collector.add({ kind: this.getSuggestionKind('boolean'), label: value ? 'true' : 'false', insertText: this.getTextForValue(value), documentation: '' }); } + private addNullSuggestion(collector: ISuggestionsCollector): void { + collector.add({ kind: this.getSuggestionKind('null'), label: 'null', insertText: 'null', documentation: '' }); + } + private addEnumSuggestion(schema: JsonSchema.IJSONSchema, collector: ISuggestionsCollector): void { if (Array.isArray(schema.enum)) { schema.enum.forEach((enm) => collector.add({ kind: this.getSuggestionKind(schema.type), label: this.getLabelForValue(enm), insertText: this.getTextForValue(enm), documentation: '' })); - } else if (schema.type === 'boolean') { - this.addBooleanSuggestion(true, collector); - this.addBooleanSuggestion(false, collector); + } else { + if (this.isType(schema, 'boolean')) { + this.addBooleanSuggestion(true, collector); + this.addBooleanSuggestion(false, collector); + } + if (this.isType(schema, 'null')) { + this.addNullSuggestion(collector); + } } if (Array.isArray(schema.allOf)) { schema.allOf.forEach((s) => this.addEnumSuggestion(s, collector)); @@ -323,6 +332,13 @@ export class JSONCompletion { } } + private isType(schema: JsonSchema.IJSONSchema, type: string) { + if (Array.isArray(schema.type)) { + return schema.type.indexOf(type) !== -1; + } + return schema.type === type; + } + private addDefaultSuggestion(schema: JsonSchema.IJSONSchema, collector: ISuggestionsCollector): void { if (schema.default) { collector.add({ @@ -409,7 +425,7 @@ export class JSONCompletion { return result; } result += ': '; - + if (propertySchema) { let defaultVal = propertySchema.default; if (typeof defaultVal !== 'undefined') { @@ -417,7 +433,8 @@ export class JSONCompletion { } else if (propertySchema.enum && propertySchema.enum.length > 0) { result = result + this.getSnippetForValue(propertySchema.enum[0]); } else { - switch (propertySchema.type) { + var type = Array.isArray(propertySchema.type) ? propertySchema.type[0] : propertySchema.type; + switch (type) { case 'boolean': result += '{{false}}'; break; diff --git a/extensions/json/server/src/jsonParser.ts b/extensions/json/server/src/jsonParser.ts index 3aa2015c86b..5f81ee8a4a4 100644 --- a/extensions/json/server/src/jsonParser.ts +++ b/extensions/json/server/src/jsonParser.ts @@ -104,7 +104,7 @@ export class ASTNode { if ((schema.type).indexOf(this.type) === -1) { validationResult.warnings.push({ location: { start: this.start, end: this.end }, - message: nls.localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}', schema.type.join()) + message: nls.localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}', schema.type.join(', ')) }); } } diff --git a/extensions/json/server/src/test/completion.test.ts b/extensions/json/server/src/test/completion.test.ts index 269249e245e..1741d08f165 100644 --- a/extensions/json/server/src/test/completion.test.ts +++ b/extensions/json/server/src/test/completion.test.ts @@ -29,7 +29,7 @@ suite('JSON Completion', () => { assert.equal(applyEdits(document, [ matches[0].textEdit ]), resultText); } }; - + var testSuggestionsFor = function(value: string, stringAfter: string, schema: JsonSchema.IJSONSchema, test: (items: CompletionItem[], document: ITextDocument) => void) : Thenable { var uri = 'test://test.json'; @@ -191,6 +191,34 @@ suite('JSON Completion', () => { ]).then(() => testDone(), (error) => testDone(error)); }); + test('Complete value with schema: booleans, null', function(testDone) { + + var schema: JsonSchema.IJSONSchema = { + type: 'object', + properties: { + 'a': { + type: 'boolean' + }, + 'b': { + type: ['boolean', 'null'] + }, + } + }; + Promise.all([ + testSuggestionsFor('{ "a": /**/ }', '/**/', schema, result => { + assert.strictEqual(result.length, 2); + assertSuggestion(result, 'true'); + assertSuggestion(result, 'false'); + }), + testSuggestionsFor('{ "b": "/**/ }', '/**/', schema, result => { + assert.strictEqual(result.length, 3); + assertSuggestion(result, 'true'); + assertSuggestion(result, 'false'); + assertSuggestion(result, 'null'); + }) + ]).then(() => testDone(), (error) => testDone(error)); + }); + test('Complete with nested schema', function(testDone) { var content = '{/**/}'; -- GitLab